当前位置: 首页 > article >正文

冲击大厂算法面试=>链表专题【链表反转之局部反转升级版】

目录标题

  • 多重局部反转之K 个一组翻转链表
    • 上代码
    • 题解呀
    • 实在不会的时候记住

多重局部反转之K 个一组翻转链表

在这里插入图片描述

上代码

整个函数通过不断地检查剩余节点数量和进行局部反转,实现了链表的分组反转,最后返回反转后的链表。这种方法有效地利用了额外的 pre 和 cur 指针来跟踪反转过程,避免了复杂的数据结构和额外的空间消耗。

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        //头节点法
        ListNode newPreHead = new ListNode(-1);
        newPreHead.next = head;

        ListNode pre = newPreHead;
        // 原地反转
        while (true) {
            // 检查剩余节点是否有k个,不足则返回
            ListNode innerCur = pre;
            int i = 0;
            while (i < k) {
                innerCur = innerCur.next;
                i++;
                if (innerCur == null) {
                    return newPreHead.next;
                }
            }

            // 翻转k个节点,操作k-1次就行
            // 1 2 3 -> 2 1 3
            // 目标:反转从 pre.next 开始的 k 个节点
            ListNode cur = pre.next;// 1
            for (int j = 0; j < k - 1; j++) {
                // 在每次循环中,node1 是当前要反转的节点
                ListNode node1 = cur.next;
                // 断开 cur 和 node1 的连接,准备反转 node1
                cur.next = node1.next;
                // 将 node1 插入到 pre 的后面,反转 node1
                node1.next = pre.next;
                // 更新 pre 的 next 指向反转后的 node1
                pre.next = node1;
            }
            // 更新 pre,准备处理下一组节点
            pre = cur;
        }
    }
}

在这里插入图片描述

题解呀

本题的难点在于连续的局部反转
核心代码:

// 翻转k个节点,操作k-1次就行
// 1 2 3 -> 2 1 3
// 目标:反转从 pre.next 开始的 k 个节点
ListNode cur = pre.next;// 1
for (int j = 0; j < k - 1; j++) {
    // 在每次循环中,node1 是当前要反转的节点
    ListNode node1 = cur.next;
    // 断开 cur 和 node1 的连接,准备反转 node1
    cur.next = node1.next;
    // 将 node1 插入到 pre 的后面,反转 node1
    node1.next = pre.next;
    // 更新 pre 的 next 指向反转后的 node1
    pre.next = node1;
}
// 更新 pre,准备处理下一组节点
pre = cur;

举例子说明核心代码

初始链表结构如下:
newPreHead -> 1 -> 2 -> 3 -> 4 -> 5

newPreHead 是虚拟头结点,初始 pre 指向 newPreHead。
cur 指向 1,即当前组的第一个节点。
node1 将在反转过程中表示下一个要反转的节点。
-----------------------------------
第一次反转(k=2)
步骤 1: 初始化 cur 和 node1
newPreHead -> 1 -> 2 -> 3 -> 4 -> 5
   ^         ^     ^
   |         |     |
  pre       cur   node1
-----------------------------------

步骤 2: 断开 cur 和 node1 的连接,准备反转 node1
【cur.next = node1.next;2
newPreHead -> 1 -> - -> 3 -> 4 -> 5
   ^         ^     ^
   |         |     |
  pre       cur   node1
  
-----------------------------------
步骤 3: 将 node1 插入到 pre 后面,反转 node1
【node1.next = pre.next;<-<-<-
              |    |2
newPreHead -> 1 -> - ->3 -> 4 -> 5
   ^         ^     ^
   |         |     |
  pre       cur   node1
  
步骤 4:再次执行【pre.next = node1;| -> -> -> -> -> -> >
   |                   |
   |          <-<-<-   | 
   |          |    |   | 
   |2 < - 
newPreHead    1 -> - ->3 -> 4 -> 5
   ^         ^     ^
   |         |     |
  pre       cur   node1

-----------------------------------
步骤 5: 更新 pre,准备处理下一组节点
【 pre = cur;】
newPreHead -> 2 -> 1 -> 3 -> 4 -> 5
			  	   ^   
			  	   |   
			      cur
			      pre 
此时,pre.next 指向了 2,node1.next 指向了 1,完成了第一次反转。
第二轮初始化就会变成,node1=4成为要反转的点
newPreHead -> 2 -> 1 -> 3 -> 4 -> 5
			  	   ^    ^    ^
			  	   |    |    |   
			      pre  cur  node1
-----------------------------------
直到循环结束

实在不会的时候记住

通过数据结构来简化问题

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        
        Deque<ListNode> stack = new ArrayDeque<ListNode>();
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        while (true) {
            int count = 0;
            ListNode tmp = head;
            //我们把 k 个数压入栈中,然后弹出来的顺序就是翻转的
            while (tmp != null && count < k) {
                stack.add(tmp);
                tmp = tmp.next;
                count++;
            }

            //不相等 说明到最后了 退出
            if (count != k) {
                //不翻转
                p.next = head;
                break;
            }
            
            //栈不为空  翻转
            while (!stack.isEmpty()){
                p.next = stack.pollLast();
                p = p.next;
            }
            
            head = tmp;
        }
        return dummy.next;
    }
}

好用的话就点个赞吧!!!

在这里插入图片描述


http://www.kler.cn/a/289543.html

相关文章:

  • Linux探秘坊-------1.系统核心的低语:基础指令的奥秘解析(1)
  • LLM - 使用 LLaMA-Factory 微调大模型 Qwen2-VL SFT(LoRA) 图像数据集 教程 (2)
  • yolov7论文翻译
  • 异步提交Django
  • uniapp vue里按钮上的文字,换行的方法,用rich-text
  • Python 实现阿里滑块全攻略
  • 1、正则表达式
  • C++ | Leetcode C++题解之第394题字符串解码
  • Elasticsearch检索原理
  • 2024.9.2 作业
  • Loadrunner12录制时,目标网站打不开的解决办法
  • 光敏电阻传感器详解(STM32)
  • redis之地理空间geo实战以及选项详解
  • Recyclerview部分列固定部分列滑动学习备忘
  • linux 下转化 ppk 文件 为openssh 文件(private,public)
  • 3600关成语填字APP游戏ACCESS\EXCEL数据库
  • 使用脚本编写 HTTP 查询的更有效方法
  • SprinBoot+Vue高校实验室管理微信小程序的设计与实现
  • 网站如何针对不同的DDOS进行防御?
  • 黑马JavaWeb开发笔记10(前端完结)——Vue路由介绍入门、前端工程打包、nginx前端部署
  • IP SSL证书如何实现IP的https
  • Nginx中间件配置
  • RLHF(带有人类反馈的强化学习)初探
  • 科研绘图系列:python语言制标准差的直方图(STD histogram plot)
  • 模拟登录页,华为账号一键登录
  • Charles抓包全流程(Mac端+iOS端)