[Java·算法·困难]LeetCode25. K 个一组翻转链表

news2024/9/20 5:58:35

每天一题,防止痴呆

  • 题目
  • 示例
  • 分析思路1
  • 题解1
  • 分析思路2
  • 题解2
  • 分析思路3
  • 题解3

👉️ 力扣原文

题目

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

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

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例

在这里插入图片描述

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

在这里插入图片描述

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

分析思路1

链表分区为已翻转部分+待翻转部分+未翻转部分
每次翻转前,要确定翻转链表的范围,这个必须通过 k 此循环来确定
需记录翻转链表前驱和后继,方便翻转完成后把已翻转部分和未翻转部分连接起来
初始需要两个变量 pre 和 end,pre 代表待翻转链表的前驱,end 代表待翻转链表的末尾
经过k此循环,end 到达末尾,记录待翻转链表的后继 next = end.next
翻转链表,然后将三部分链表连接起来,然后重置 pre 和 end 指针,然后进入下一次循环
特殊情况,当翻转部分长度不足 k 时,在定位 end 完成后,end==null,已经到达末尾,说明题目已完成,直接返回即可

题解1

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
	    if (head == null || head.next == null){
	            return head;
	    }
	    //定义一个假的节点
	    ListNode dummy = new ListNode(0);
	    dummy.next = head;
	
	    //初始化pre和end都指向dummy
	    //pre指每次要翻转的链表的头结点的上一个节点
	    //end指每次要翻转的链表的尾节点
	    ListNode pre = dummy;
	    ListNode end = dummy;
	
	    while (end.next != null) {
	        //循环k次,找到需要翻转的链表的结尾,
	        //这里每次循环要判断end是否等于空,因为如果为空,end.next会报空指针异常。
	        for (int i = 0; i < k && end != null; i++){
	            end = end.next;
	        } 
	        //如果end==null,即需要翻转的链表的节点数小于k,不执行翻转。
	        if (end == null) break;
	        //先记录下end.next,方便后面链接链表
	        ListNode next = end.next;
	        //然后断开链表
	        end.next = null;
	
	        //记录下要翻转链表的头节点
	        ListNode start = pre.next;
	        //翻转链表,pre.next指向翻转后的链表。1->2 变成2->1。 dummy->2->1
	        pre.next = reverse(start);
	        //翻转后头节点变到最后。通过.next把断开的链表重新链接。
	        start.next = next;
	        //将pre换成下次要翻转的链表的头结点的上一个节点。即start
	        pre = start;
	        //翻转结束,将end置为下次要翻转的链表的头结点的上一个节点。即start
	        end = pre;
	    }
	    return dummy.next;
	}

	/**
	 * 反转链表   
	 */
	private ListNode reverse(ListNode head) {
	    ListNode prev=null,temp;
	        while(head != null){
	            temp = head.next;
	            head.next = prev;
	            prev = head;
	            head = temp;
	        }
	        return prev;
	}
}

执行结果
在这里插入图片描述

分析思路2

首先创建一个dummy节点,并将它的 next 指向 head 节点。然后算法遍历整个链表,计算链表的长度。接下来,算法使用两个指针 prev 和 curr 来标记待翻转链表的前一个节点和第一个节点。算法使用一个嵌套循环,在每 k 个节点处将链表进行反转操作。在内部循环中,算法通过交换节点的 next 值,反转链表的前 k 个节点。最后,算法更新 prev 和 curr 指针的位置,并返回链表的头部(dummy.next)。

题解2

public ListNode reverseKGroup(ListNode head, int k) {
    ListNode dummy = new ListNode(0);
    ListNode prev = dummy;
    ListNode curr = head;
    ListNode after;
    dummy.next = head; // dummy指向头节点
    int length = 0;
    while (head != null) {
        length++; // 获取链表长度
        head = head.next;
    }

    for (int i = 0; i < length / k; i++) {
        for (int j = 0; j < k - 1; j++) {
            after = curr.next;  // 保存当前节点下一个节点的指针
            curr.next = after.next; // 把当前节点的下一个节点指向下下个节点
            after.next = prev.next; // 把当前节点的下一个节点指向链表的前面部分
            prev.next = after;  // 把新的节点插入到链表前面部分和后面部分之间
        }
        prev = curr; // 更新prev指针为当前子链表的尾节点
        curr = prev.next; // 更新curr指针为下一个子链表的头节点
    }
    return dummy.next; // 返回修改后的链表
}

执行结果
在这里插入图片描述

分析思路3

使用递归来实现该算法:每次递归处理 k 个节点,如果不足 k 个节点则不翻转,直接返回。每次递归处理的子链表可以看做是一个整体,它的头节点是翻转后的子链表的尾节点,它的尾节点是翻转后的子链表的头节点。

题解3

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode curr = head;
        int count = 0;
        while (curr != null && count < k) { // 检查是否有 k 个节点
            curr = curr.next;
            count++;
        }
        if (count == k) { // 如果有 k 个节点,递归处理后面的子链表
            curr = reverseKGroup(curr, k); // 反转后面的 k 个节点
            while (count > 0) { // 反转当前子链表的 k 个节点
                ListNode temp = head.next;
                head.next = curr;
                curr = head;
                head = temp;
                count--;
            }
            head = curr; // 更新头节点为当前子链表的尾节点
        }
        return head; // 返回修改后的链表
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb--用户注册登录案例

用户注册登录案例1 用户登录1.1 需求分析1.2 环境准备1.3 代码实现2 用户注册2.1 需求分析2.2 代码编写3 SqlSessionFactory工具类抽取目标&#xff1a; 能够完成用户登录注册案例的实现能够完成SqlSessionFactory工具类的抽取 接下来我们通过两个比较常见的案例&#xff0c;一…

国家能源局持续发文,赛宁网安以实力响应电力网络靶场建设

​​一、政策导向 ​​国家能源局连续三年发文 推进电力网络靶场建设 2021.1. 国家能源局印发《2021电力安全监管重点工作任务》提出&#xff1a;加强电网及网络安全监管。推进电力行业网络安全仿真验证环境&#xff08;靶场&#xff09;建设&#xff0c;组织开展电力行业网…

如何构建一个稳定、可靠、安全的大型工业机械远程监控系统?

在工业机械设备的应用过程中&#xff0c;对于生产的质量、效率等要求都非常高&#xff0c;尤其是大型设备往往需要多人协同操作&#xff0c;如果没有实时的数据反馈和监控系统进行数据处理&#xff0c;就会出现数据偏差甚至错误现象。当前&#xff0c;国内大型工业机械设备数量…

AB测试-A/B Test

网络上有很多类似名称&#xff0c;又名A/B试验&#xff0c;ab test。 文章目录一、应用场景二、什么是AB测试三、AB测试可以解决什么问题四、AB测试的流程五、AB测试常见的误区六、AB测试的原理一、应用场景 以公司遇到的问题及需求入手&#xff0c;帮助大家建立感性认识。总结…

动态规划:leetcode 198.打家劫舍、213.打家劫舍II、337.打家劫舍III

leetcode 198.打家劫舍leetcode 213.打家劫舍IIleetcode 337.打家劫舍IIIleetcode 198.打家劫舍你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相…

GitCode使用教程

目录 0.前言 1. 安装git 2. 注册 gitcode 3. 创建SSH key 4. GitCode 中配置公钥 5. 新建项目 6. clone项目 7. push 项目 0.前言 笔者之前大致知道&#xff0c;2020年9月10日&#xff0c;CSDN正式推出全新升级的开源平台 GitCode&#xff0c;不过鉴于稳定性原因一直没…

第十章 优化stop功能

优化stop功能 突然发现其实stop存在边缘案例是没有通过的&#xff0c;比如我图中红框中的obj.prop 当加上这句代码后&#xff0c;运行测试案例是不能通过的&#xff0c;原因分析&#xff1a; stop后已经把依赖清除了&#xff0c;obj.prop又走了get&#xff0c;触发了依赖收集…

Java 获取文件后缀名【一文总结所有方法】

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Delphi 中 FireDAC 数据库连接(管理事务)

参见&#xff1a;Delphi 中 FireDAC 数据库连接&#xff08;总览&#xff09;描述了如何使用FireDAC来管理DBMS事务。FireDAC提供TFDConnection和TFDTransaction组件来帮助你处理数据库事务。一、概述默认情况下&#xff0c;FireDAC应用程序在自动提交模式下工作&#xff0c;当…

Spring Cloud Alibaba全家桶(四)——微服务调用组件Feign

前言 本文小新为大家带来 微服务调用组件Feign 的相关知识&#xff0c;具体内容包含什么是Feign&#xff0c;Spring Cloud Alibaba快速整合OpenFeign&#xff0c;Spring Cloud Feign的自定义配置及使用&#xff08;包括&#xff1a;日志配置、契约配置、自定义拦截器实现认证逻…

五方面提高销售流程管理的CRM系统

销售充满了不确定性&#xff0c;面对不同的客户&#xff0c;销售人员需要采用不同的销售策略。也正因为这种不确定性&#xff0c;规范的销售流程对企业尤为重要&#xff0c;它会让销售工作更加有效&#xff0c;快速地实现成交。下面小编给您推荐个不错的CRM销售流程管理系统。 …

BQ25071QWDQCRQ1示意图ISO6721BQDRQ1引脚配置ISO7330CQDWRQ1数字隔离器

1、BQ25071QWDQCRQ1应用程序示意图BQ25071 1A 单输入、单节线性电池充电器是一款高度集成的线性 LiFePO4 电池充电器&#xff0c;适用于空间受限的便携式应用。它接受来自 USB 端口或交流适配器的电力&#xff0c;为单节 LiFePO4 电池提供高达 1A 的充电电流。该器件具有单个电…

【DaVinci Developer专题】-45-自动生成SWC中所有Runnable对应的C文件

点击返回「Autosar从入门到精通-实战篇」总目录 案例背景(共5页精讲): 在DaVinci Developer中,以Test_A_SWC的Runnable为例,见图0-1。我们现在尝试自动生成一个包含Test_A_SWC_Init和Test_A_SWC_Main函数原型(也是适用于 C/S Port Serve Runnable)的C文件。 图0-1 目…

详解旨在提升EVM底层性能的兼容公链Monad

EVM带来的繁荣2020年以太坊链上DeFi的蓬勃发展使得EVM成为关注焦点&#xff0c;大部分DeFi项目都开始基于以太坊公链&#xff0c;这也使得EVM成为行业的标杆&#xff0c;不少链都加入了EVM大军&#xff0c;比如polygon、BSC、fantom等等&#xff0c;而EVM也使得链上生态进一步繁…

【算法笔记】队列与优先队列

队列与优先队列 1.队列的概念 只允许在一端插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff1b;进行插入操作的一端称为队尾&#xff08;入队列&#xff09;&#xff0c;进行删除操作的一端称为队头&#xff08;出队列&#xff09;&#xff1b; 队列…

离散事件动态系统

文章目录离散事件动态系统ppt离散事件系统建模离散事件动态系统的基本组成元素离散事件动态系统仿真具体建模petri建模实例离散事件动态系统 ppt ppt 仿真建模步骤 离散事件系统建模 from&#xff1a;离散事件系统建模 离散事件动态系统的基本组成元素 &#xff08;1&am…

腾讯云服务器CVM和轻量应用服务器区别对比

腾讯云新推出的轻量应用服务器Lighthouse和原来的CVM云服务器有什么区别&#xff1f;轻量应用服务器Lighthouse是一种易于使用和管理、适合承载轻量级业务负载的云服务器&#xff0c;主要用于Web网站应用&#xff0c;轻量服务器使用及后期运维更加简单方便&#xff1b;云服务器…

TypeError: Axes3D.view_init() got an unexpected keyword argument ‘roll‘——版本问题

解决办法 删除roll关键字参数。 掉坑过程 今天在学习matplotlib绘制3D图形时&#xff0c;使用的是matplotlib官网提供的例子Plot 2D data on 3D plot 敲好代码后&#xff0c;运行时报错TypeError: Axes3D.view_init() got an unexpected keyword argument ‘roll’ 看来官…

k8s学习之路 | Day18 Pod 基础

文章目录Pod 基础认知什么是 PodPod 的示例 yamlPod 的形式Pod 的多容器协同Pod 的生命周期容器的类型应用容器初始化容器临时容器静态 Pod什么是静态 Pod静态 Pod 位置Pod 探针机制探针类型Probe 配置项探针案例Pod 基础认知 什么是 Pod https://kubernetes.io/zh-cn/docs/c…

黑马程序员Java教程学习笔记(四)

学习视频&#xff1a;https://www.bilibili.com/video/BV1Cv411372m 如侵权&#xff0c;请私信联系本人删除 文章目录黑马程序员Java教程学习笔记&#xff08;四&#xff09;static&#xff1a;修饰成员变量、内存机制static&#xff1a;修饰成员方法、内存机制static访问注意事…