leetCode之k个一组翻转链表

这个是个“困难”级别的题目,题目描述如下:

给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。

示例 :

给定这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

为了解决这个问题,我想需要思考下面的问题
(1)如何知道翻转了多少组
(2)每一组的翻转需要记录那些节点才能保证后面组的翻转能够正确执行

1、为了解决问题(1),先遍历一遍链表求出整个链表的长度len,知道了len,那么就可以知道翻转了多少组了

        int len=0;
        while(now!=null)
        {
            len++;
            if(len==k)
                newHead=now;
            now=now.next;
        }
        //now回到头,表示现在遍历的节点
        now=head;
        //翻转的组数次turnNumber
        int turnNumber=len/k;

2、知道了遍历的组数之后,进行第二次变量,并且为了保证每一组翻转之后都能够继续正确的执行下去,遍历过程中需要记录以下节点。
(1)前一组翻转之后的尾节点beforeLast
(2)目前翻转组翻转之后的头节点partHead
(3)目前翻转组翻转之后的尾节店partLast
而在翻转过程中,需要记录的节点有:
(1)目前遍历的节点now
(2)目前遍历节点的前一个节点pre

解决了这两个问题之后,问题就迎刃而解了,每一组的处理过程如下:
(1)因为最一开始的now就是翻转之后的这个组的尾节店,所有partLast=now
(2)这一组不断的翻转,然后把最后一点节点设为partHead
(3)翻转这个组之后,把beforeLast.next指向partHead,然后partLast就是新的beforeLast

具体的代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        //先遍历一遍得到链表的长度len和翻转之后的头节点
        ListNode now=head;
        ListNode newHead=now;
        int len=0;
        while(now!=null)
        {
            len++;
            if(len==k)
                newHead=now;
            now=now.next;
        }
        //now回到头,表示现在遍历的节点
        now=head;
        //翻转的组数次turnNumber
        int turnNumber=len/k;
        //beforeLast表示之前部分的尾部
        ListNode beforeLast=null;
        ListNode pre=null;
        for(int i=0;i<turnNumber;i++)
        {
            //partLast表示每一部分翻转之后的头部,partHead表示头
            ListNode partHead=null;
            ListNode partLast=now;
            int nowK=1;
            while(nowK<=k)
            {
                if(nowK==k)
                    partHead=now;
                nowK++;
                ListNode nowNext=now.next;
                now.next=pre;
                pre=now;
                now=nowNext;
            }
            if(beforeLast!=null)
                beforeLast.next=partHead;
            beforeLast=partLast;
            
            
        }
        if(beforeLast!=null)
                beforeLast.next=now;
        
        
        return newHead;
    }
}

提交结果如下
在这里插入图片描述
上面即为个人的非递归解法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值