力扣92(java&python)-反转链表Ⅱ(中等)

题目:

给你单链表的头指针 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 }

posted on 2022-09-19 16:04  我不想一直当菜鸟  阅读(80)  评论(0编辑  收藏  举报