C 反转链表的每k个节点
我正在准备一次技术面试,我一直在写这个程序来反转链表中的每个k节点 比如说C 反转链表的每k个节点,c,algorithm,linked-list,C,Algorithm,Linked List,我正在准备一次技术面试,我一直在写这个程序来反转链表中的每个k节点 比如说 1->2->3->4->5->6 //Linked List 2->1->4->3->6->5 //Output for k=2 编辑: 这是我的密码。我只得到6->5作为输出 struct node* recrev(struct node* noode,int c) { struct node* root=noode,*temp,*final,*prev=
1->2->3->4->5->6 //Linked List
2->1->4->3->6->5 //Output for k=2
编辑:
这是我的密码。我只得到6->5作为输出
struct node* recrev(struct node* noode,int c)
{
struct node* root=noode,*temp,*final,*prev=NULL;
int count=0;
while(root!=NULL && count<c)
{
count++;
temp=root->link;
root->link=prev;
prev=root;
root=temp;
}
if(temp!=NULL)
noode->link=recrev(temp,c);
else
return prev;
}
struct node*recrev(struct node*noode,int c)
{
结构节点*root=noode,*temp,*final,*prev=NULL;
整数计数=0;
while(root!=NULL&&countlink;
root->link=prev;
prev=根;
根=温度;
}
如果(温度!=NULL)
noode->link=recrev(温度,c);
其他的
返回上一个;
}
谢谢你的帮助,谢谢
编辑:我试图实现Eran Zimmerman的算法,如下所示
struct node* rev(struct node* root,int c)
{
struct node* first=root,*prev,*remaining=NULL;
int count=0;
while(first!=NULL && count<c)
{
count++;
prev=first->link;
first->link=remaining;
remaining=first;
first=prev;
}
return remaining;
}
struct node* recc(struct node* root,int c)
{
struct node* final,*temp,*n=root,*t;
int count=0;
while(n!=NULL)
{
count=0;
temp=rev(n,c);
final=temp;
while(n!=NULL && count<c)
{
printf("inside while: %c\n",n->data); // This gets printed only once
if(n->link==NULL) printf("NULL"); //During first iteration itself NULL gets printed
n=n->link;
final=final->link;
count++;
}
}
final->link=NULL;
return final;
}
struct node*rev(struct node*root,int c)
{
结构节点*first=root,*prev,*remaining=NULL;
整数计数=0;
while(first!=NULL&&countlink;
第一->链接=剩余;
剩余=第一;
第一个=上一个;
}
返回剩余值;
}
结构节点*recc(结构节点*root,int c)
{
结构节点*final,*temp,*n=root,*t;
整数计数=0;
while(n!=NULL)
{
计数=0;
温度=转速(n,c);
最终=温度;
while(n!=NULL&&countdata);//只打印一次
如果(n->link==NULL)printf(“NULL”);//在第一次迭代过程中,会打印NULL
n=n->link;
最终=最终->链接;
计数++;
}
}
final->link=NULL;
返回最终结果;
}
我会这样做:
init curr (node pointer) to point to the beginning of the list.
while end of list is not reached (by curr):
- reverse(curr, k)
- advance curr k times
reverse是一个函数,它从curr开始反转前k个元素
这可能不是最优雅或最有效的实现,但它可以工作并且非常简单
要回答有关您添加的代码的问题,请执行以下操作:
您返回了prev,它一直处于高级状态。您应该返回列表的开头。我喜欢您使用递归,尽管它可能不是最佳解决方案。我可以从您的代码中看出,您在设计它时会深入思考。您离答案只有一步之遥 原因:在递归情况下,您忘记返回新的
根节点
if(temp!=NULL)
noode->link=recrev(temp,c);
// You need return the new root node here
// which in this case is prev:
// return prev;
else
return prev;
(我假设这是一个单链接列表。)您可以保留一个临时指针(我们称之为nodek
),并在while循环中将其前进k次。这将需要O(k)。现在您有一个指向列表开头和子列表最后一个元素的指针。要在此处反转,请从head中删除O(1)并添加到nodek
,即O(1)。对所有元素执行此操作,使其再次成为O(k)。现在将root更新为nodek,并再次在nodek上运行while循环(以获得nodek
)并再次重复整个过程。记住在此过程中进行任何错误检查。
此解决方案将在O(n)处运行,只需要O(1)个额外空间。下面是一个伪代码
temp = main_head = node.alloc ();
while ( !linked_list.is_empty () )
{
push k nodes on stack
head = stack.pop ();
temp->next = head;
temp = head;
while ( !stack.empty () )
{
temp->next = stack.pop ();
temp = temp->next;
}
}
我已经做了这个代码的演示实现。请原谅这个混乱的实现。这将适用于k
的任何值。每个k
大小的段在内环中分别反转,不同的段在进入内环之前在外环中相互链接。temp
跟踪最后的nk
大小的子列表的ode和head
保存下一个子列表的下一个值,我们将它们链接起来。使用显式堆栈进行反转
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int a;
struct _node *next;
} node_t;
typedef struct _stack {
node_t *arr[128];
int top;
} stack_t;
void stk_init (stack_t *stk)
{
stk->top = -1;
}
void push (stack_t *stk, node_t *val)
{
stk->arr[++(stk->top)] = val;
}
node_t *pop (stack_t *stk)
{
if (stk->top == -1)
return NULL;
return stk->arr[(stk->top)--];
}
int empty (stack_t *stk)
{
return (stk->top == -1);
}
int main (void)
{
stack_t *stk = malloc (sizeof (stack_t));
node_t *head, *main_head, *temp1, *temp;
int i, k, n;
printf ("\nEnter number of list elements: ");
scanf ("%d", &n);
printf ("\nEnter value of k: ");
scanf ("%d", &k);
/* Using dummy head 'main_head' */
main_head = malloc (sizeof (node_t));
main_head->next = NULL;
/* Populate list */
for (i=n; i>0; i--)
{
temp = malloc (sizeof (node_t));
temp->a = i;
temp->next = main_head->next;
main_head->next = temp;
}
/* Show initial list */
printf ("\n");
for (temp = main_head->next; temp != NULL; temp = temp->next)
{
printf ("%d->", temp->a);
}
stk_init (stk);
/* temp1 is used for traversing the list
* temp is used for tracing the revrsed list
* head is used for tracing the sublist of size 'k' local head
* this head value is used to link with the previous
* sublist's tail value, which we get from temp pointer
*/
temp1 = main_head->next;
temp = main_head;
/* reverse process */
while (temp1)
{
for (i=0; (temp1 != NULL) && (i<k); i++)
{
push (stk, temp1);
temp1 = temp1->next;
}
head = pop (stk);
temp->next = head;
temp = head;
while (!empty (stk))
{
temp->next = pop (stk);
if (temp->next == NULL)
break;
temp = temp->next;
}
}
/* Terminate list with NULL . This is necessary as
* for even no of nodes the last temp->next points
* to its previous node after above process
*/
temp->next = NULL;
printf ("\n");
for (temp = main_head->next; temp != NULL; temp = temp->next)
{
printf ("%d->", temp->a);
}
/* free linked list here */
return 0;
}
#包括
#包括
类型定义结构节点{
INTA;
结构_节点*下一步;
}节点t;
typedef结构栈{
节点_t*arr[128];
int top;
}堆叠;
void stk_init(堆栈*stk)
{
stk->top=-1;
}
无效推送(堆栈*stk,节点*val)
{
stk->arr[++(stk->top)]=val;
}
节点\u t*pop(堆栈\u t*stk)
{
如果(stk->top==-1)
返回NULL;
返回stk->arr[(stk->top)--];
}
int空(堆栈*stk)
{
返回(stk->top==-1);
}
内部主(空)
{
stack_t*stk=malloc(sizeof(stack_t));
节点头、*主头、*temp1、*temp;
inti,k,n;
printf(“\n输入列表元素数:”);
scanf(“%d”和“&n”);
printf(“\n输入k的值:”);
scanf(“%d”和“&k”);
/*使用虚拟头“主头”*/
main_head=malloc(sizeof(node_t));
main_head->next=NULL;
/*填充列表*/
对于(i=n;i>0;i--)
{
temp=malloc(sizeof(node_t));
温度->a=i;
临时->下一步=主头->下一步;
主头->下一个=温度;
}
/*显示初始列表*/
printf(“\n”);
用于(临时=主头->下一步;临时!=NULL;临时=临时->下一步)
{
printf(“%d->”,temp->a);
}
stk_init(stk);
/*temp1用于遍历列表
*temp用于跟踪已撤销的列表
*head用于跟踪大小为“k”的局部head子列表
*此头值用于链接上一个头
*子列表的尾值,我们从临时指针获得
*/
temp1=主头->下一步;
温度=主压头;
/*反向过程*/
while(temp1)
{
对于(i=0;(temp1!=NULL)和(inxt;
}
水头=波普(stk);
温度->下一步=头部;
温度=水头;
而(!空(stk))
{
临时->下一步=弹出(stk);
如果(临时->下一步==NULL)
打破
温度=温度->下一步;
}
}
/*使用NULL终止列表。这是必要的,因为
*即使没有节点,最后一个临时->下一个点
*在完成上述过程后返回到其上一个节点
*/
temp->next=NULL;
printf(“\n”);
用于(临时=主头->下一步;临时!=NULL;临时=临时->下一步)
{
printf(“%d->”,temp->a);
}
/*这里有免费的链接列表*/
返回0;
}
是的,我从来都不喜欢递归,所以下面是我使用迭代的一次尝试:
public Node reverse(Node head, int k) {
Node st = head;
if(head == null) {
return null;
}
Node newHead = reverseList(st, k);
st = st.next;
while(st != null) {
reverseList(st, k);
st = st.next;
}
return newHead
}
private Node reverseList(Node head, int k) {
Node prev = null;
Node curr = head;
Node next = head.next;
while(next != null && k != 1){
curr.next = prev;
prev = curr;
curr = next;
next = next.next;
--k;
}
curr.next = prev;
// head is the new tail now.
head.next = next;
// tail is the new head now.
return curr;
}
下面的解决方案使用额外的空间来存储指针,并分别反转每个列表块。最后,构建了新的列表。当我测试时,这似乎涵盖了边界条件
template <typename T>
struct Node {
T data;
struct Node<T>* next;
Node() { next=NULL; }
};
template <class T>
void advancePointerToNextChunk(struct Node<T> * & ptr,int & k) {
int count =0;
while(ptr && count <k ) {
ptr=ptr->next;
count ++;
}
k=count;}
/*K-Reverse Linked List */
template <class T>
void kReverseList( struct Node<T> * & head, int k){
int storeK=k,numchunk=0,hcount=0;
queue < struct Node<T> *> headPointerQueue;
queue <struct Node<T> *> tailPointerQueue;
struct Node<T> * tptr,*hptr;
struct Node<T> * ptr=head,*curHead=head,*kReversedHead,*kReversedTail;
while (ptr) {
advancePointerToNextChunk(ptr,storeK);
reverseN(curHead,storeK,kReversedHead,kReversedTail);
numchunk++;
storeK=k;
curHead=ptr;
tailPointerQueue.push(kReversedTail),headPointerQueue.push(kReversedHead);
}
while( !headPointerQueue.empty() || !tailPointerQueue.empty() ) {
if(!headPointerQueue.empty()) {
hcount++;
if(hcount == 1) {
head=headPointerQueue.front();
headPointerQueue.pop();
}
if(!headPointerQueue.empty()) {
hptr=headPointerQueue.front();
headPointerQueue.pop();
}
}
if( !tailPointerQueue.empty() ) {
tptr=tailPointerQueue.front();
tailPointerQueue.pop();
}
tptr->next=hptr;
}
tptr->next=NULL;}
template <class T> void reverseN(struct Node<T> * & head, int k, struct Node<T> * & kReversedHead, structNode<T> * & kReversedTail ) {
struct Node<T> * ptr=head,*tmp;
int count=0;
struct Node<T> *curr=head,*nextNode,*result=NULL;
while(curr && count <k) {
count++;
cout <<"Curr data="<<curr->data<<"\t"<<"count="<<count<<"\n";
nextNode=curr->next;
curr->next=kReversedHead;
kReversedHead=curr;
if(count ==1 ) kReversedTail=kReversedHead;
curr=nextNode;
}}
模板
结构节点{
T数据;
结构节点*下一步;
Node(){next=NULL;}
};
模板
void advancePointerToNextChunk(结构节点*&ptr,int&k){
整数计数=0;
while(ptr&&countnext;
计数++;
}
k=计数;}
/*K-反向链表*/
模板
void kReverseList(结构节点*&头,int k){
int-storeK=k,numchunk=0,hcount=0;
队列headPointerQueue;
public class ReverseEveryKNodes<K>
{
private static class Node<K>
{
private K k;
private Node<K> next;
private Node(K k)
{
this.k = k;
}
}
private Node<K> head;
private Node<K> tail;
private int size;
public void insert(K kk)
{
if(head==null)
{
head = new Node<K>(kk);
tail = head;
}
else
{
tail.next = new Node<K>(kk);
tail = tail.next;
}
size++;
}
public void print()
{
Node<K> temp = head;
while(temp!=null)
{
System.out.print(temp.k+"--->");
temp = temp.next;
}
System.out.println("");
}
public void reverse(int k)
{
head = reverseK(head, k);
}
Node<K> reverseK(Node<K> n, int k)
{
if(n==null)return null;
Node<K> next=n, c=n, previous=null;
int count = 0;
while(c!=null && count<k)
{
next=c.next;
c.next=previous;
previous=c;
c=next;
count++;
}
n.next=reverseK(c, k);
return previous;
}
public static void main(String[] args)
{
ReverseEveryKNodes<Integer> r = new ReverseEveryKNodes<Integer>();
r.insert(10);
r.insert(12);
r.insert(13);
r.insert(14);
r.insert(15);
r.insert(16);
r.insert(17);
r.insert(18);
r.print();
r.reverse(3);
r.print();
}
}