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

217 篇文章 0 订阅
174 篇文章 2 订阅

本题源自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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值