【LeetCodehot100】T24:两两交换链表中的节点 T25:K个一组翻转链表

T24:两两交换链表中的节点

题目核心是:两个两个一组,进行交换。

交换的是节点,不是数字

我们来举例只有两个节点的情况:(1->2)

原来:

1.next=2;

2.next=null

我们要变换为:

2.next=1;

1.next=null;

所以需要三步

  1. 保存2
  2. 让2指向1
  3. 修改1的next

当不止有一组时怎么办?

当:

1 → 2 → 3 → 4

我们发现问题:

第一组交换后,怎么连接后面的节点?

这时就需要用到虚拟头节点dummy

交换一组节点需要几个指针?

以a → b为例:

pre → a → b → next

需要四个。

例如:

dummy → 1 → 2 → 3

这里:

pre = dummy

a = 1

b = 2

next = 3

交换操作(核心)

原来:pre → a → b → next
第一步

pre.next=b;

第二步

a.next=b.next

a后面的b已经更新到per的后面,所以我们更新a.next为b的后面一位,就是b.next

第三步

b.next=a;

然后移动指针

交换完一组后:

pre = a

因为:

a 已经在后面

继续处理下一组。

代码实现

java 复制代码
ListNode dummy=new ListNode(0);
dummmy.next=head;
ListNode pre=dummy;

while(pre.next!=null&&pre.next.next!=null){
//交换
pre.next=b;
a.next=b.next;
b.next=a;

//移动到下一组
pre=a
}
return dummy.next;

T25:K个一组翻转链表

核心理解:

给你:1 → 2 → 3 → 4 → 5

k = 2

要求:

每 k 个节点为一组进行反转。

本质高手:

1 找到一组 k 个节点

2 把这 k 个节点反转

3 接回原链表

整体流程

例如

1 → 2 → 3 → 4 → 5

k = 3

流程:

第一步 找到一组

1 2 3

第二步 断开链表

1 → 2 → 3

后面

4 → 5

第三步 反转

3 → 2 → 1

第四步 接回原链表

3 → 2 → 1 → 4 → 5

第五步 继续下一组

4 5

不够3个

结束。

四、为什么需要 dummy 节点

很多链表题都会写:

ListNode dummy = new ListNode(0);

dummy.next = head;

结构变成

dummy → 1 → 2 → 3 → 4 → 5

作用:

统一处理头节点

因为反转后:

3 会成为新头节点

dummy可以帮我们管理这个变化。

五、关键指针

代码里会用到几个指针:

dummy

pre

end

start

next

作用:

指针 作用
dummy 虚拟头节点
pre 当前组前一个节点
end 当前组最后一个节点
start 当前组第一个节点
next 下一组开始节点

六、完整流程图

原链表

dummy → 1 → 2 → 3 → 4 → 5

第一步 找到 k 个节点

移动 end:

1

2

3

现在

pre → dummy

start → 1

end → 3

第二步 记录下一组

next = 4

第三步 断开链表

end.next = null

现在链表

1 → 2 → 3

第四步 反转链表

调用

reverse(start)

得到

3 → 2 → 1

第五步 接回链表

原来

dummy → 1 → 2 → 3

现在

dummy → 3 → 2 → 1

然后

1 → 4 → 5

最终

dummy → 3 → 2 → 1 → 4 → 5

第六步 移动指针

pre = start

end = pre

继续处理下一组。

代码实现

java 复制代码
class Solution {

    public ListNode reverseKGroup(ListNode head, int k) {

        // 创建虚拟头节点,解决头节点变化的问题
        // 例如反转后新的头节点可能不是原来的 head
        ListNode dummy = new ListNode(0);
        dummy.next = head;

        // pre:每一组反转前的那个节点
        ListNode pre = dummy;

        // end:用于寻找当前这一组的第 k 个节点
        ListNode end = dummy;

        while(true){

            // 1. 找到当前这一组的第 k 个节点
            // end 向前走 k 步
            for(int i = 0; i < k && end != null; i++){
                end = end.next;
            }

            // 如果不够 k 个节点,直接结束
            if(end == null){
                break;
            }

            // 2. 记录当前这一组的开始节点
            // pre -> start -> ... -> end
            ListNode start = pre.next;

            // 3. 记录下一组开始的位置
            // end -> next
            ListNode next = end.next;

            // 4. 断开当前这一组链表
            // 例如:
            // 1 → 2 → 3 → 4 → 5
            // 变成
            // 1 → 2 → 3 → null    4 → 5
            end.next = null;

            // 5. 反转当前这一组链表
            // reverse(start) 返回新的头节点
            // 例如 1→2→3 变成 3→2→1
            pre.next = reverse(start);

            // 6. 把反转后的链表接回去
            // start 此时已经变成这一组的最后一个节点
            // 让它指向下一组
            start.next = next;

            // 7. 移动指针,为下一组做准备
            // pre 移动到这一组的最后一个节点
            pre = start;

            // end 重新回到 pre 的位置
            end = pre;
        }

        // 返回新的头节点
        return dummy.next;
    }


    // 反转链表函数
    private ListNode reverse(ListNode head){

        // pre:反转后的链表头
        ListNode pre = null;

        // cur:当前正在处理的节点
        ListNode cur = head;

        while(cur != null){

            // 保存下一个节点
            ListNode next = cur.next;

            // 反转指针
            // 例如:2 → 1
            cur.next = pre;

            // pre 前进一步
            pre = cur;

            // cur 前进一步
            cur = next;
        }

        // 返回反转后的头节点
        return pre;
    }
}
相关推荐
nananaij1 小时前
【LeetCode-04 数组异或操作 python解法】
python·算法·leetcode
毕设源码-朱学姐1 小时前
【开题答辩全过程】以 基于Springboot的养老服务管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
少许极端1 小时前
算法奇妙屋(三十一)-递归、回溯与剪枝的综合问题 4
算法·剪枝·回溯·递归
mjhcsp1 小时前
C++随机调整(Random Adjustment):优化算法的核心随机策略
java·c++·算法
Yupureki2 小时前
《C++实战项目-高并发内存池》6.内存释放流程
c语言·开发语言·数据结构·c++·算法·哈希算法
qingwufeiyang_5302 小时前
Nacos学习笔记
java·笔记·学习·spring cloud·服务发现
charlie1145141912 小时前
嵌入式现代C++开发——三路比较运算符
开发语言·c++·学习·算法·嵌入式·编程指南
2401_900151542 小时前
C++编译期正则表达式
开发语言·c++·算法
天涯明月19932 小时前
服务网格完全指南:从基础概念到生产实践
java·服务器·数据库·分布式·微服务