L25

  1. K 个一组翻转链表
    给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例:

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

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

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

说明:

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换

1.递推法

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        //递推方法的使用
        if(head == null) return head;
        ListNode a, b;
        a = b= head;
        for(int i = 0; i < k; i++){//边界条件
            if(b == null) return head;//如不足k个,则返回
            b = b.next;
        }
        ListNode newHead = reverse(a, b);
        a.next = reverseKGroup(b, k);
        return newHead;
    }
    ListNode reverse(ListNode a, ListNode b){//反转[a,b)
        //容易成环
        ListNode n1, n2, n3;
        n1 = a;
        n2 = a.next;
        n3 = null;
        
        while (n2 != b){
            n3 = n2.next;
            n2.next = n1;
            n1 = n2;
            n2 = n3;
        }
        return n1;//返回头节点
        
    }
    ListNode reverse2(ListNode a, ListNode b){//反转[a,b)
        
        ListNode n1, n2, n3;
        if(a == null) return a;
        n1 = null;//设置null
        n2 = a;
        n3 = null;
        while(n2 != b){
            n3 = n2.next;
            n2.next = n1;
            n1 = n2;
            n2 = n3;
        }
        return n1;
        
    }
}

2.迭代法

class Solution {
	public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        //还是先指定一个暂时的头结点
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        for(int i = 0; i < n; i++){
            int tmp = sc.nextInt();
            cur.next = new ListNode(tmp);
            cur = cur.next;
        }
        int k = sc.nextInt();
        Solution ss = new Solution();
        ListNode result = ss.reverseKGroup(head.next, k);
        while (result != null){
            System.out.print(result.val + " ");
            result = result.next;
        }
    }
    public ListNode reverseKGroup(ListNode head, int k) {
        if(k < 2) return head;
        ListNode pre = new ListNode(-1);
        pre.next = head;//最终只需要返回pre.next;
        ListNode last = pre;//last为上一单元的最后一个
        int cnt = 1;
        ListNode cur = head;//用来移动
        ListNode save = null;
        while(cur != null){//不能只使用一个变量cur,cur表示当前的最后一个节点,但是随着反转之后,cur就会变好,所以需要另一个变量先存储下一个节点
            save = cur.next;//先存起来
            if(cnt == k){
                ListNode start = last.next;//该单元的第一个
                ListNode end = cur;//该单元的最后一个
                ListNode next = cur.next;//下一处理单元的第一个点,先保存下来

                //内部反转,一个一个的来,不能直接使用start,end
                ListNode n1 = start, n2 = n1.next;
                while(n2 != next){
                    ListNode tmp = n2.next;//保存
                    n2.next = n1;
                    n1 = n2;
                    n2 = tmp;
                }

                //前后两段连接
                last.next = end;
                start.next = next;
                last = start;//更新last,不用更新next
                cnt = 0;
            }
            //cur = cur.next;
            cur = save;//这里再往前走一步
            cnt++;
        }
        return pre.next;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值