描述
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。
例如:
给出的链表为
1
→
2
→
3
→
4
→
5
→
N
U
L
L
,
m
=
2
,
n
=
4
,
1\to 2 \to 3 \to 4 \to 5 \to NULL,m=2,n=4,
1→2→3→4→5→NULL,m=2,n=4,
返回
1
→
4
→
3
→
2
→
5
→
N
U
L
L
.
1\to 4\to 3\to 2\to 5\to NULL.
1→4→3→2→5→NULL.
数据范围: 链表长度
0
<
s
i
z
e
≤
1000
,
0
<
m
≤
n
≤
s
i
z
e
0 < size \le 1000,0 < m \le n \le size
0<size≤1000,0<m≤n≤size,链表中每个节点的值满足
∣
v
a
l
∣
≤
1000
|val| \le 1000
∣val∣≤1000
要求:时间复杂度 O(n) ,空间复杂度 O(n)
进阶:时间复杂度 O(n),空间复杂度 O(1)
示例1
输入:{1,2,3,4,5},2,4
返回值:{1,4,3,2,5}
示例2
输入:{5},1,1
返回值:{5}
题解:
在学会了BM1.反转链表之后,要解决这个问题就很简单了,前一题是整个链表反转,这一题是部分反转,这上一题就是这道题的前置问题啊。那我们肯定是要先找到了第m个位置才能开始反转链表,而反转的部分就是从第m个位置到第n个位置,反转这部分的时候就参照BM1.反转链表:
while(cur != null){
//断开链表,要记录后续一个
ListNode temp = cur.next;
//当前的next指向前一个
cur.next = pre;
//前一个更新为当前
pre = cur;
//当前更新为刚刚记录的后一个
cur = temp;
}
具体做法:
step 1:我们可以在链表前加一个表头,后续返回时去掉就好了,因为如果要从链表头的位置开始反转,在多了一个表头的情况下就能保证第一个节点永远不会反转,不会到后面去。
step 2:使用两个指针,一个指向当前节点,一个指向前序节点。
step 3:依次遍历链表,到第m个的位置。
step 4:对于从m到n这些个位置的节点,依次断掉指向后续的指针,反转指针方向。
step 5:返回时去掉我们添加的表头。
图示:
class Solution:
def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
#加个表头
res = ListNode(-1)
res.next = head
#前序节点
pre = res
#当前节点
cur = head
#找到m
for i in range(1,m):
pre = cur
cur = cur.next
#从m反转到n
for i in range(m, n):
temp = cur.next
cur.next = temp.next
temp.next = pre.next
pre.next = temp
#返回去掉表头
return res.next