给定一个链表,一次颠倒链表k的节点并返回其修改列表。如果节点的数量不是k的倍数,那末最后的剩余节点应该保持原样。

来源:互联网 发布:修改软件下载 编辑:程序博客网 时间:2024/06/16 16:07

本题源自LeetCode

--------------------------------------------------------------------

思路:

利用栈结构的解法,时间复杂度O(n),空间复杂度O(k)
1:从左到右遍历链表,如果栈的大小不等于k,就将节点不断压入栈中
2:当栈的大小第一次达到k时,说明第一次凑齐了k个节点进行逆序,从栈中依次弹出
这些节点,并根据弹出顺序依次链接,这一组逆序完成后,需要记录一下新的头部,
同时第一组的最后一个节点(原来是头结点)应该链接下一个节点。
3:步骤2之后,当栈的大小每次达到k时,说明又凑齐了一组应该进行逆序的节点,从
栈中依次弹出这些节点,并根据弹出的顺序重新链接。这一组逆序完成后,该组的第一
个节点(原来是该组最后一个节点)应该被上一组的最后一个节点链接上,这一组的最
后一个节点(原来是该组第一个节点)应该链接下一个节点。然后继续去凑下一组,直
到链表被遍历完成。
我们可以不用栈,直接在链表中进行操作

代码:

void reverseCore(ListNode* start,ListNode* end,ListNode* &newStart,ListNode* &newEnd){  //用的指针的引用,也可以用 **指针的指针ListNode* pNext=NULL;        ListNode* p=start;        ListNode* pre=NULL;        newStart=end;        newEnd=start;        ListNode* nextNode=end->next;        while(p!=nextNode){            pNext=p->next;            p->next=pre;            pre=p;            p=pNext;        }    }       ListNode *reverseKGroup(ListNode *head, int k) {        ListNode* p=head;        ListNode* newHead=NULL;        ListNode* start=head;        ListNode* pre=NULL;        ListNode* pNext=NULL;        int count=1;        while(p){            pNext=p->next;            if(count==k){   //节点数量到K 个 反转部分链表            ListNode* newStart=NULL;       ListNode* newEnd=NULL;                reverseCore(start,p,newStart,newEnd);                if(newHead==NULL)   //新链表的头指针                    newHead=newStart;                if(pre)                    pre->next=newStart;   //保持链表链接                newEnd->next=pNext;                        pre=newEnd;               //保存上一个链表的尾节点                start=pNext;              //保存每个局部链表的头                count=0;                  //count清零            }            p=pNext;            count++;        }        return newHead?newHead:head;    }

思路2 :

考虑 用递归即 翻转pairs,翻转x~x+(k-1)之间的节点, x->next = reverseKGroup(x+k,k)

代码:

   ListNode* reverseCore(ListNode* start,ListNode* end){  //用的指针的引用,也可以用 **指针的指针ListNode* pNext=NULL;        ListNode* p=start;        ListNode* pre=NULL;        while(p!=end){            pNext=p->next;            p->next=pre;            pre=p;            p=pNext;        }       return pre;    }       ListNode *reverseKGroup(ListNode *head, int k) {        if(head==NULL||k<2)            return head;        ListNode *p=head;        for(int i=0;i<k;i++){            if(!p)                return head;            p=p->next;        }        ListNode* newHead=reverseCore(head,p);  //反转K链表        head->next=reverseKGroup(p,k);  //保持链表不断。        return newHead;    }

思路3  非递归

遍历链表,每遍历k个节点,就反转。并且保持链表不断开

ListNode *reverseKGroup(ListNode *head, int k) {        if(head==NULL||k<2)            return head;        ListNode *p=head;        int len=0;        while(p){            p=p->next;            len++;        }        ListNode* root=new ListNode(0);        root->next=head;        ListNode* pre=root;        p=head;        ListNode* pNext=NULL;        for(int i=0;i<len/k;i++){   //循环len/k次            for(int j=1;j<k;j++){    //每次反转k 个节点                pNext=p->next;                p->next=pNext->next;                pNext->next=pre->next;                pre->next=pNext;            }            pre=p;       //保持链表不断开            p=p->next;        }        return root->next;    }


阅读全文
0 0