算法leetcode|25. K 个一组翻转链表(rust重拳出击)

news2025/4/7 4:07:04

文章目录

  • 25. K 个一组翻转链表:
    • 样例 1:
    • 样例 2:
    • 提示:
    • 进阶:
  • 分析:
  • 题解:
    • rust
    • go
    • c++
    • c
    • python
    • java


25. K 个一组翻转链表:

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

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

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

样例 1:

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

样例 2:

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

提示:

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

进阶:

  • 你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?

分析:

  • 面对这道算法题目,二当家的陷入了沉思。
  • 利用指针做位置交换,递归或者遍历处理,直接上就行了。
  • 递归还是比较直观,简单,看代码注释,非常详细。
  • 遍历也不难,但是单向链表需要前结点来指向当前结点,所以需要一个哑结点来统一处理,手工管理内存的话,需要最后释放掉哑结点。

题解:

rust

// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
//   pub val: i32,
//   pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
//   #[inline]
//   fn new(val: i32) -> Self {
//     ListNode {
//       next: None,
//       val
//     }
//   }
// }
impl Solution {
    pub fn reverse_k_group(mut head: Option<Box<ListNode>>, k: i32) -> Option<Box<ListNode>> {
        let mut next_group_head = &mut head;
        // 查看剩余部分长度是否大于等于 k
        for _ in 0..k {
            if next_group_head.is_none() {
                // 不够k就不用翻转了
                return head;
            }
            next_group_head = &mut next_group_head.as_mut().unwrap().next;
        }
        // 递归翻转后面
        let mut new_head = Solution::reverse_k_group(next_group_head.take(), k);
        // 将前半部分逐个拼到new_head(已经翻转好的后半部分)的前面
        while head.is_some() {
            // 正在处理翻转的结点
            let node = head.as_mut().unwrap();
            // 临时存放正在处理的结点的下一个结点
            let next = node.next.take();
            // 将正在处理的结点挂在新头的前面
            node.next = new_head.take();
            // 移动指针(正在处理的结点变成已经处理好的新头结点)
            new_head = head;
            // 移动指针(临时存放正在处理的结点的下一个结点变成将要处理的结点)
            head = next;
        }
        return new_head;
    }
}

go

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseKGroup(head *ListNode, k int) *ListNode {
    nextGroupHead := head
	// 查看剩余部分长度是否大于等于 k
	for i := 0; i < k; i++ {
		if nextGroupHead == nil {
			// 不够k就不用翻转了
			return head
		}
		nextGroupHead = nextGroupHead.Next
	}
	// 递归翻转后面
	newHead := reverseKGroup(nextGroupHead, k)
	// 将前半部分逐个拼到new_head(已经翻转好的后半部分)的前面
	for i := 0; i < k; i++ {
		// 临时存放正在处理的结点的下一个结点
		next := head.Next
		// 将正在处理的结点挂在新头的前面
		head.Next = newHead
		// 移动指针(正在处理的结点变成已经处理好的新头结点)
		newHead = head
		// 移动指针(临时存放正在处理的结点的下一个结点变成将要处理的结点)
		head = next
	}
	return newHead
}

c++

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode *nextGroupHead = head;
        // 查看剩余部分长度是否大于等于 k
        for (int i = 0; i < k; ++i) {
            if (nextGroupHead == nullptr) {
                // 不够k就不用翻转了
                return head;
            }
            nextGroupHead = nextGroupHead->next;
        }
        // 递归翻转后面
        ListNode *newHead = reverseKGroup(nextGroupHead, k);
        // 将前半部分逐个拼到new_head(已经翻转好的后半部分)的前面
        for (int i = 0; i < k; ++i) {
            // 临时存放正在处理的结点的下一个结点
            ListNode *next = head->next;
            // 将正在处理的结点挂在新头的前面
            head->next = newHead;
            // 移动指针(正在处理的结点变成已经处理好的新头结点)
            newHead = head;
            // 移动指针(临时存放正在处理的结点的下一个结点变成将要处理的结点)
            head = next;
        }
        return newHead;
    }
};

c

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseKGroup(struct ListNode* head, int k){
    struct ListNode *nextGroupHead = head;
    // 查看剩余部分长度是否大于等于 k
    for (int i = 0; i < k; ++i) {
        if (nextGroupHead == NULL) {
            // 不够k就不用翻转了
            return head;
        }
        nextGroupHead = nextGroupHead->next;
    }
    // 递归翻转后面
    struct ListNode *newHead = reverseKGroup(nextGroupHead, k);
    // 将前半部分逐个拼到new_head(已经翻转好的后半部分)的前面
    for (int i = 0; i < k; ++i) {
        // 临时存放正在处理的结点的下一个结点
        struct ListNode *next = head->next;
        // 将正在处理的结点挂在新头的前面
        head->next = newHead;
        // 移动指针(正在处理的结点变成已经处理好的新头结点)
        newHead = head;
        // 移动指针(临时存放正在处理的结点的下一个结点变成将要处理的结点)
        head = next;
    }
    return newHead;
}

python

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        next_group_head = head
        # 查看剩余部分长度是否大于等于 k
        for _ in range(k):
            if next_group_head is None:
                # 不够k就不用翻转了
                return head
            next_group_head = next_group_head.next
        # 递归翻转后面
        new_head = self.reverseKGroup(next_group_head, k)
        # 将前半部分逐个拼到new_head(已经翻转好的后半部分)的前面
        for _ in range(k):
            # 临时存放正在处理的结点的下一个结点
            next = head.next
            # 将正在处理的结点挂在新头的前面
            head.next = new_head
            # 移动指针(正在处理的结点变成已经处理好的新头结点)
            new_head = head
            # 移动指针(临时存放正在处理的结点的下一个结点变成将要处理的结点)
            head = next
        return new_head


java

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode nextGroupHead = head;
        // 查看剩余部分长度是否大于等于 k
        for (int i = 0; i < k; ++i) {
            if (nextGroupHead == null) {
                // 不够k就不用翻转了
                return head;
            }
            nextGroupHead = nextGroupHead.next;
        }
        // 递归翻转后面
        ListNode newHead = reverseKGroup(nextGroupHead, k);
        // 将前半部分逐个拼到new_head(已经翻转好的后半部分)的前面
        for (int i = 0; i < k; ++i) {
            // 临时存放正在处理的结点的下一个结点
            ListNode next = head.next;
            // 将正在处理的结点挂在新头的前面
            head.next = newHead;
            // 移动指针(正在处理的结点变成已经处理好的新头结点)
            newHead = head;
            // 移动指针(临时存放正在处理的结点的下一个结点变成将要处理的结点)
            head = next;
        }
        return newHead;
    }
}
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;

        while (pre.next != null) {
            ListNode tail = pre;
            // 查看剩余部分长度是否大于等于 k
            for (int i = 0; i < k; ++i) {
                tail = tail.next;
                if (tail == null) {
                    return dummy.next;
                }
            }
            // 指针后移
            pre = reverse(pre, tail);
        }

        return dummy.next;
    }

    private ListNode reverse(ListNode pre, ListNode tail) {
        ListNode newTail = pre.next;
        ListNode newHead = tail.next;
        ListNode head    = newTail;
        while (newHead != tail) {
            ListNode next = head.next;
            head.next = newHead;
            newHead = head;
            head = next;
        }
        pre.next = newHead;
        return newTail;
    }
}

非常感谢你阅读本文~
欢迎【点赞】【收藏】【评论】~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~


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

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

相关文章

是谣传还是真强?GitHub一战封神的“SQL优化手册”获赞过百万

这份“SQL优化本质手册”的口碑之所以能够火爆&#xff0c;完全是因为这部作品本身就是作者付诸于自己的多年开发经验之作的原因&#xff0c;所以只要走进书中&#xff0c;看过之后的人都知道&#xff0c;你很难不把自己代入其中与作者一起产生深深地共鸣。 收获&#xff0c;不…

DFS——剪枝优化迭代加深

文章目录概述优化搜索顺序排除等效冗余可行性剪枝最优性剪枝例题小猫爬山木棒迭代加深概述加成序列总结概述 优化搜索顺序 不同的搜索顺序会产生不同的搜索树形态&#xff0c;与可行性剪枝结合&#xff0c;去除非法状态&#xff0c;按照一定顺序可使规模大幅度减小。 例&#…

新能源电池进入高速发展阶段,数商云S2B2C商城赋能企业分销渠道管理更便捷

在国家政策扶持下&#xff0c;我国新能源汽车市场飞速发展&#xff0c;产品供给不断丰富、企业创新活力竞相迸发、使用环境日臻完善以及消费者认可度日益提高&#xff0c;近年来更是产销两旺&#xff0c;新能源汽车产销量屡创新高&#xff0c;作为新能源车的核心部件——电池&a…

面试官问我 ,try catch 应该在for循环里面还是外面?

前言 有个老哥昨天被面试官欺负了&#xff0c;但是是被这个问题&#xff08;标题&#xff09;欺负的&#xff1f; 其实是个比较基础的问题&#xff0c;只要有了解过&#xff0c;叙述是非常简单OK的。 只要有初学者觉得有疑惑&#xff0c;那么我相信不止是他一个。 所以&#…

青少年等级考试【Python通关干货】(一级)

青少年等级考试【Python通关干货】&#xff08;一级&#xff09; 1. 编程模式 1&#xff09;交互式编程 在交互式环境的提示符>>>下&#xff0c;直接输入代码&#xff0c;按回车&#xff0c;就可以立刻得到代码执行结果。 交互式编程缺憾是没有保存下来&#xff0c;下…

2023 目标,与君共勉

新的一年&#xff0c;立一些目标&#xff0c;与君共勉 技术相关目标 csdn申请专业领域创作认证通过、博客专家认证通过掘金创作等级可以达到LV6等级掘金发表两个小册&#xff0c;有50人以上订阅csdn原先的进阶专栏&#xff0c;增加到100篇文章&#xff0c;有50人以上订阅csdn…

2021地理设计组一等奖:面向游客的旅游路线优化设计——以丹霞山景区为例

作品简介 一、背景与意义 随着旅游业的快速发展与人们对旅行质量要求的提升&#xff0c;旅游者对旅游服务的内容要求也越来越高&#xff0c;其中的旅游导航便是一项需求率极高的服务。然而传统的导航服务多是基于时间或距离成本进行网络分析而提供的路径设计&#xff0c;极少考…

R16 Dormant BWP

微信同步更新欢迎关注同名modem协议笔记 接上篇BWP结尾&#xff0c;R15时SCell的激活和去激活是通过Pcell的MAC CE&#xff0c;R16在Scell上引入dormant BWP的概念&#xff0c;可以通过DCI 控制Scell在dormant BWP和non-dormant BWP间进行切换&#xff0c;相比于MAC CE的控制方…

SpringBoot 基于 OAuth2 统一身份认证流程详解

1. 目标 了解OAUTH2统一认证基本概念了解OAUTH2协议流程了解OAUTH2各种模式类型了解Spring Security OAuth设计 2. 分析 传统登陆认证介绍 单点登陆认证介绍 OAuth2简介 OAuth2角色 OAuth2协议流程介绍 OAuth2授权类型 OAuth2授权码模式流程 OAuth2简化模式 OAuth2密码…

JavaScript 入门基础 / 概念介绍(一)

JavaScript 入门基础 / 概念介绍&#xff08;一&#xff09; 1.初识JavaScript 1.1 JavaScript历史 1995年&#xff0c;网景公司一名程序员布兰登艾奇利用十天完成了JavaScript设计&#xff0c;网景公司最初将它命名为LiveScript&#xff0c;后与Sun公司合作将其改名为JavaS…

外行人如何通过学习软件测试转行IT

随着互联网的快速发展&#xff0c;现在很多行业都被智能化取代&#xff0c;IT行业从业人员剧增&#xff0c;很多不是IT行业的人都想转行IT&#xff0c;那么对于不是IT行业的人&#xff0c;如何能快速转行变成IT人呢&#xff1f;软件测试是你最好的选择。对于一个不是本行业的人…

内科大深度学习期末复习笔记

文章目录一.选择判断1.1矩阵与 神经网络模型 与 深度学习模型 关系1.2 机器学习 与 深度学习 在训练数据中的区别1.3点乘与叉乘区别1.4 深度学习模型 浅层与深层 关系1.5线性关系与非线性 权重和偏置1.6 超参数&#xff08;训练数据与可调整数据&#xff08;var&#xff09;&am…

10年经验hr亲授:刷完阿里P8架构师的RocketMQ核心手册,进大厂稳了

为什么要选择RocketMQ? 市场上几大消息队列对比如下&#xff1a; 总结一下&#xff1a; 选择中间件的可以从这些维度来考虑&#xff1a;可靠性&#xff0c;性能&#xff0c;功能&#xff0c;可运维行&#xff0c;可拓展性&#xff0c;社区活跃度。目前常用的几个中间件&…

基于容器的PaaS混合云的几种形式

概述 这是 Gartner 的一个图&#xff0c;提供了全球的基于容器的 PaaS 公有云、混合云服务的梳理展示&#xff1a; 这里提供一个其他的视角&#xff1a; 中国市场&#xff0c;基于容器的 PaaS 混合云&#xff08;公有云 私有云&#xff09;的相关厂商及产品。 ❗️ 注意&am…

PyTorch笔记 - Batch\Layer\Instance\Group\Weight Normalization 源码

欢迎关注我的CSDN:https://blog.csdn.net/caroline_wendy 本文地址:https://blog.csdn.net/caroline_wendy/article/details/128416962 Normalization in NN: Batch Normalization: per channel across mini-batchtorch.nn.BatchNorm1d / torch.nn.BatchNorm2dLayer Normaliz…

2023世界杯新媒体传播热点盘点 中国元素之中国馆、富而喜悦!

2022年卡塔尔世界杯于上周日落幕&#xff0c;作为“后新冠时代”的首个大型全球体育赛事&#xff0c;也同时被多个“史上首次”与“历史之最”所装点。作为普通球迷亦或资深网友的你&#xff0c;对本届世界杯的流行趋势与媒体热点有多少了解呢&#xff1f;富而喜悦&#xff0c;…

RISCV-V-1.0向量扩展指令集学习

大部分内容翻译自 riscv-v-spec-1.0 部分参考&#xff1a; 【《RISC-V “V“ Vector Extension Version 1.0》阅读笔记】_LPL之芯的博客-CSDN博客 RISC-V “V”(向量)扩展规范v0.9文档&#xff08;2&#xff09; - 知乎 (zhihu.com) 文章目录3. Vector Extension Programmers M…

开放下载丨2023年二十万字技术年货新鲜送达

文章目录一、再谈数字化二、关于技术合集三、思想沉淀与书写价值四、写在最后一、再谈数字化 21世纪是无可争议的数字时代。过去20多年来&#xff0c;中国企业踏上了一个伟大而又艰难的数字化转型征程。虽然在行业数字化转型的深度和广度方面&#xff0c;头部企业已经相当领先…

IU酒店打造齐鲁文化旅游发展新高地

淄博&#xff0c;位处鲁中&#xff0c;是黄河三角洲生态经济和蓝色经济区的交汇处。四季分明的气候造就了这座齐国故都的生态多样性&#xff0c;南高北低的地理位置使其峻岭平原兼具&#xff0c;鲁中的位置又赋予他交通枢纽的重要性。这里历史气息浓厚&#xff0c;社会文化自由…

@SuppressWarnings使用-屏蔽一些无关紧要的警告

SuppressWarnings 用法 与idea设置相关-参考 作用&#xff1a;用于抑制编译器产生警告信息&#xff0c;不显示波浪提示线。 我们在写代码的时候&#xff0c;不论是导入的包&#xff0c;还是声明的对象&#xff0c;有时候会出现黄线&#xff0c;感觉就很难受&#xff01; Su…