# 「每日一题」力扣 92 反转链表 II

你好啊,我是蓝莓,今天是每日一题的第 34 天。

题目清单一起刷力扣 (opens new window)

引用力扣题目92 反转链表 II (opens new window)

# 题目描述

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

示例 1:

img

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

示例 2:

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

提示:

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

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

# 实现

思路 1

  • 比较简单的思路是,我们先遍历一遍链表来寻找几个关键的节点
  • 然后再对中间部分的链表进行翻转,随后调整关键位置的指向

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* reverseBetween(ListNode* head, int left, int right) {
        ListNode* dummyHead = new ListNode(-1, head);

        // 找到 left 和 right 代表的节点
        ListNode* leftPre = nullptr;  // left 的前一个节点
        ListNode* leftNode = nullptr;  // left 节点
        ListNode* rightNode = nullptr;  // right 节点
        ListNode* rightNext = nullptr;  // right 后一个节点

        ListNode* pre = dummyHead;  // 遍历过程中的前一个节点
        ListNode* cur = head;  // 遍历过程中的后一个节点

        // 寻找节点
        int counter = 1;
        while( cur != nullptr ) {
            if( counter == left ) {
                leftPre = pre;
                leftNode = cur;
            }
            
            if( counter == right ) {
                rightNode = cur;
                rightNext = cur->next;
            }

            pre = cur;
            cur = cur->next;
            counter++;
        }

        cur = leftNode;
        pre = leftPre;
        // 翻转链表
        while( cur != rightNext ) {
            ListNode* next = cur->next;

            cur->next = pre;
            pre = cur;
            cur = next;
        }

        // 调整翻转后的中间部分的链表指向关系
        leftNode->next = rightNext;
        leftPre->next = rightNode;

        return dummyHead->next;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

思路 2

  • 在第一种方法中,我们遍历了两次链表才把问题解决
  • 其实核心问题是要确定,在什么范围内才翻转链表?
  • 根据题目描述,我们要在给定的范围内才需要对链表进行翻转
  • 那就是这样的一个范围 counter >= left && counter <= right; 其中 counter 代表当前是第几个节点

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* reverseBetween(ListNode* head, int left, int right) {
        ListNode* dummyHead = new ListNode(-1, head);

        // 找到 left 和 right 代表的节点
        ListNode* leftPre = nullptr;  // left 的前一个节点
        ListNode* leftNode = nullptr;  // left 节点
        ListNode* rightNode = nullptr;  // right 节点
        ListNode* rightNext = nullptr;  // right 后一个节点

        ListNode* pre = dummyHead;  // 遍历过程中的前一个节点
        ListNode* cur = head;  // 遍历过程中的后一个节点

        int counter = 1;
        while( cur != nullptr ) {
            ListNode* next = cur->next;

            if( counter == left ) {
                leftPre = pre;
                leftNode = cur;
            }

            if( counter == right ) {
                rightNode = cur;
                rightNext = next;
            }

            // 如果在给定范围内 那就翻转链表
            if( counter >= left && counter <= right ) {
                cur->next = pre;
            }

            // 移动到下一个节点
            pre = cur;
            cur = next;
            counter++;
        }

        // 调整指针的指向
        leftPre->next = rightNode;
        leftNode->next = rightNext;
        
        return dummyHead->next;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
最近更新: 1/25/2025, 9:28:19 PM
「每日一题」力扣 92 反转链表 II

酷酷的算法   |