题目:

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例1:

输入:head = [1,2,3,4,5], left = 2, right = 4

输出:[1,4,3,2,5]

示例2:

输入:head = [5], left = 1, right = 1

输出:[5]

提示:

链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n

进阶: 你可以使用一趟扫描完成反转吗?

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/reverse-linked-list-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

一、头插法

1.首先定义一个虚拟头结点指向原始头结点,可以减少对头结点的特殊处理,将头结点当做普通结点处理;

2.定义两个指针一个为pre,一个为cur;

3.确定pre和cur指针的位置,需要根据题中给定的left值进行确定,将pre移动到第一个需要反转的结点的前面,将cur移动到需要反转的第一个结点上;

4.将cur后面一个结点temp保存,将当前cur指向cur的下下个结点,即cur.next=cur.next.next , 然后将保存的结点插入到pre后面;

5.重复步骤4;

6.最后返回dummyHead.next。

解释:

temp.next = pre.next这里为什么不能写成temp.next = cur?

看上面的图解就可以看出,cur所指向的结点没有变过,但是所在的位置是一直在变化的,pre和cur中间会一直插入结点,而每次插入都是在pre的后面。如果写成temp.next = cur就会删除上面已经反转的结点,比如4和3。

java代码:

 1 /**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 * int val;
5 * ListNode next;
6 * ListNode() {}
7 * ListNode(int val) { this.val = val; }
8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 * }
10 */
11 class Solution {
12 public ListNode reverseBetween(ListNode head, int left, int right) {
13 ListNode dummyHead = new ListNode(0,head);
14 //定义两个指针pre和cur
15 ListNode pre = dummyHead;
16 ListNode cur = dummyHead.next;
17
18 //先确定两个指针的初始位置,pre应该在left-1,cur=left
19 for(int i = 1; i < left; i++){
20 pre = pre.next;
21 cur = cur.next;
22 }
23 //插入
24 for(int j = 1; j < right - left + 1; j++){
25 //保存cur的下一个结点
26 ListNode temp = cur.next;
27 //使cur指向它的下下个结点
28 cur.next = cur.next.next;
29 //将保存的结点插入
30 temp.next = pre.next;
31 pre.next = temp;
32 }
33 return dummyHead.next;
34
35 }
36 }

 python3代码:

 1 # Definition for singly-linked list.
2 # class ListNode:
3 # def __init__(self, val=0, next=None):
4 # self.val = val
5 # self.next = next
6 class Solution:
7 def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
8 dummyHead = ListNode(0,head)
9 pre,cur = dummyHead,dummyHead.next
10
11 # 确定pre和cur的位置
12 for i in range(1,left):
13 cur = cur.next
14 pre = pre.next
15
16 # 插入操作
17 for i in range(1,right-left+1):
18 temp = cur.next
19 # 如果temp是尾结点cur.next为none
20 cur.next = temp.next if temp else None
21
22 temp.next = pre.next
23 pre.next = temp
24
25 return dummyHead.next

 二、递归

reverseBetween():含义就是将拿到的链表进行反转,然后返回反转后的链表的头结点(递归的过程想的太仔细,很容易绕进去,其实清楚最后返回的头结点的是谁最重要)
详解参考@编程狂想曲
java代码:
 1 /**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 * int val;
5 * ListNode next;
6 * ListNode() {}
7 * ListNode(int val) { this.val = val; }
8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 * }
10 */
11 class Solution {
12 public ListNode reverseBetween(ListNode head, int left, int right) {
13 if (left == 1){
14 return reversTopN(head, right);
15 }
16 //翻转
17 ListNode between = reverseBetween(head.next, left-1, right-1);
18 //将翻转后的新头结点挂在原来的head之后
19 head.next = between;
20 //返回链表
21 return head;
22 }
23 //nextnode第n个结点之后的结点
24 ListNode nextnode = null;
25 private ListNode reversTopN(ListNode head, int n){
26 //如果只翻转一个,把下一个结点直接放在头结点后
27 if(n == 1){
28 nextnode = head.next;
29 return head;
30 }
31 ListNode newHead = reversTopN(head.next, n-1);
32 //头结点的下一个结点指向头结点
33 head.next.next = head;
34 head.next = nextnode;
35 return newHead;
36 }
37 }

力扣92(java&python)-反转链表Ⅱ(中等)的更多相关文章

  1. 力扣(LeetCode)反转链表 个人题解

    反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶:你可以迭代或 ...

  2. 力扣 - 92. 反转链表II

    目录 题目 思路1(迭代) 代码 复杂度分析 思路2(递归) 代码 复杂度分析 题目 92. 反转链表 II 思路1(迭代) 将反转链表分成3个部分:前一段未反转的部分.待反转链表部分.后一段未反转部 ...

  3. 力扣—Reorder List(重排链表)python实现

    题目描述: 中文: 给定一个单链表 L:L0→L1→…→Ln-1→Ln ,将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点 ...

  4. 力扣——Partition List(分隔链表) python实现

    题目描述: 中文: 给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前. 你应当保留两个分区中每个节点的初始相对位置. 示例: 输入: head = ...

  5. 【力扣】82. 删除排序链表中的重复元素 II

    存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字. 返回同样按升序排列的结果链表. 示例 1: 输入:hea ...

  6. 第92题:反转链表II

    一. 问题描述 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NUL ...

  7. LeetCode(92):反转链表 II

    Medium! 题目描述: 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明:1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5-&g ...

  8. 力扣题目汇总(反转字符串中的单词,EXCEL表列序号,旋置矩阵)

    反转字符串中的单词 III 1.题目描述 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例 1: 输入: "Let's take LeetCode ...

  9. 力扣(LeetCode)环形链表 个人题解

    给定一个链表,判断链表中是否有环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 -1,则在该链表中没有环. 示例 1: 输入: ...

  10. 力扣题解-面试题22. 链表中倒数第K个节点

    题目描述 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5. ...

随机推荐

  1. docker部署文件

  2. [【stars-one】Android图标生成器 PC工具

    原文: [stars-one]Android图标生成器 - Stars-One的杂货小窝 一款Android开发者的PC工具软件,可以快速生成android开发需要使用的xml矢量图标文件 起因 个人 ...

  3. 一个简单的百万并发的TCP服务器的实现。

    我们紧接着上篇文章,看看我们上节课的代码有什么问题? 可以明显的看出来上节课的代码公用了一个同样的缓冲区进行读写,正常的情况下我们需要封装一个结构体,让每个对应的客户端的FD都有独立的结构进行读写还有 ...

  4. 一张图搞清楚wait、sleep、join、yield四者区别,面试官直接被征服!

    写在开头 在线程的生命周期中,不同状态之间切换时,可以通过调用sleep().wait().join().yield()等方法进行线程状态控制,针对这一部分知识点,面试官们也会做做文章,比如问你这些方 ...

  5. 使用ConnectivityManager.bindProcessToNetwork绑定特殊网络

    最近测试那边提了一个bug,经过排查后发现其原因:是因为连接的Wi-Fi无法上网,因此在Android系统的多网络策略中,可以上网的SIM移动网络被设置为系统默认网络,投屏组件docker传输与反控模 ...

  6. java 手动生成jni头文件(JNI静态注册)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  7. SQL奇遇记:解锁 SQL 的秘密

    数据库基础 在我们探究SQL语言之旅的起点,首先要对数据库的核心理念有所了解.数据库在现代生活中无处不在,每次网购.网页浏览.即时通讯,都在产生数据.简单来说,数据库就是按一定数据结构组织.存储.管理 ...

  8. 记录--Vue中的$attrs你真的会用吗?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 先来看一个业务需求: 项目经常会遇到产品经理要求你做某组件一样的功能,还要在它的基础上增加东西.如何只用少量代码高效的二次封装组件呢? 例 ...

  9. Go | 浅谈包管理模式

    任何一门编程语言都离不开对各种工具包的使用,工具包的管理就显得异常重要了.Go 的包管理方式是逐渐演进的,本文介绍Go语言的两种包管理模式. GOPATH模式引包(不推荐) 在 1.5 版本之前,所有 ...

  10. CentOS 安装webmin

    下载地址 http://download.webmin.com/download/yum/ 安装依赖 sudo yum -y install openssl perl perl-Net-SSLeay ...