leetcode 刷题记 (003--链表)

题目描述:
K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5

题目链接:click me !

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

思路一:

​ 这道题级别虽然是“困难”,但只要想通了就很简单,模拟一下过程就可以得到结果。

  1. 我们先给一个哑结点(dummy)用来指向链表,最后返回dummy.next
  2. 在每一次翻转子链表的过程中我们都需要维护4个指针:prev、start、end、next
  3. prev的作用是用来 连接 已翻转链表和待翻转链表,start 和 end 是用来翻转每个子链表,next 是用来记录下一个待翻转子链表的头部
  4. 我们把翻转每个子链表的任务交给reverse()来完成,返回每个子链表翻转后的头结点
  5. 每次翻转完成之后我们都需要维护以上的4个指针

主要步骤如下:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

每次翻转都经过上述4步,直到end.next == null,结束翻转,返回dummy.next

Java代码实现:

// 结点类
class ListNode {
     int val;
     ListNode next;
     ListNode(int x) { val = x; }
}

public class Solution01 {

    public static ListNode reverseKGroup(ListNode head, int k) {
        // 给一个哑结点,用来指向列表的头部
        ListNode dummy = new ListNode(0);
        dummy.next = head;

        ListNode prev = dummy;
        ListNode end = dummy;

        while (end.next != null) {
            int n = k;
            // 找到每个子链表的最后一个元素
            while (end != null && (n--) > 0) end = end.next;
            if (end == null) break; // 子链表中元素个数不足K个

            ListNode start = prev.next;   // start指向当前待翻转子链表的头部
            ListNode the_next = end.next;   // 记录下一个子链表的头结点
            end.next = null;    // 把将要翻转的子链表和下一个待翻转的子链表断开

            // 翻转当前链表
            prev.next = reverse(start);     
            
            // 维护prev、start、end、next
            // 将翻转后的链表和待翻转链表连起来
            start.next = the_next;
            prev = start;
            end = start;
        }

        return dummy.next;
    }

	// 翻转子链表
    private static ListNode reverse(ListNode curr) {
        // 确保curr不为空
        ListNode prev = null;
        ListNode next;
        while (curr != null) {
            next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}

思路二: 递归

K个一组翻转链表,具体到每一段,其实就是一个简单的翻转链表的问题
所以我们只需要将每一个段翻转的头结点返回,拼接到前一段的翻转后的尾结点即可

Java实现:

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null) return null;
        ListNode cur = head;
        int i = k;
        // 先遍历找到下一段的开头
        while(i>0&&cur!=null){
            cur = cur.next;
            i--;
        }
        // 如果没有到k个,那么原顺序返回
        if(i>0) return head;
        // 关键在于这个位置,返回值拼接到当前段翻转后的尾结点即可
        // 而尾结点就是原链表在当前段的头
        ListNode pre = reverseKGroup(cur,k);
        cur = head;
        i = k;
        while(i>0){
            ListNode tmp = cur.next;
            cur.next= pre;
            pre = cur;
            cur = tmp;
            i--;
        }
        return pre;
        
        
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值