链表反转

题目

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ m ≤ n ≤ 链表长度。

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL

题解

方法一:递归

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
61
62
63
64
65
66
67
68
69
70
71
72
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def createLink_rearinsert(lista):
head = ListNode(-1)
rear = head
for i in lista:
new_node=ListNode(i)
rear.next=new_node
rear=new_node
return head.next
class Solution:
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""

if not head:
return None

left, right = head, head
stop = False
def recurseAndReverse(right, m, n):
nonlocal left, stop

# base case. Don't proceed any further
if n == 1:
return

# Keep moving the right pointer one step forward until (n == 1)
right = right.next

# Keep moving left pointer to the right until we reach the proper node
# from where the reversal is to start.
if m > 1:
left = left.next

# Recurse with m and n reduced.
recurseAndReverse(right, m - 1, n - 1)

# In case both the pointers cross each other or become equal, we
# stop i.e. don't swap data any further. We are done reversing at this
# point.
if left == right or right.next == left:
stop = True

# Until the boolean stop is false, swap data between the two pointers
if not stop:
left.val, right.val = right.val, left.val

# Move left one step to the right.
# The right pointer moves one step back via backtracking.
left = left.next

recurseAndReverse(right, m, n)
return head
if __name__=="__main__":
a=[1,4,3,2,5,2]
new_a=createLink_rearinsert(a)
a1 = Solution()
p=a1.reverseBetween(new_a,2,4)
list1=[]
while(p!=None):
list1.append(p.val)
#print(p.val)
p=p.next
print(list1)
[1, 2, 3, 4, 5, 2]

方法二:迭代

若有一个三个不同结点组成的链表 A → B → C,实现反转结点中的链接成为 A ← B ← C

  • 试想两个结点翻转时,令pre指针指向A,cur指向B

    1
    2
    3
    4
    third = cur.next # 方便找到一结点
    cur.next = prev
    prev = cur
    cur = third
  • 迭代实现上述过程即可完成链表翻转

  • 如上所述,我们需要两个指针 prev 和 cur。

  • prev 指针初始化为 None,cur 指针初始化为链表的 head。

  • 一步步地向前推进 cur 指针,prev 指针跟随其后。

  • 如此推进两个指针,直到 cur 指针到达从链表头起的第 m 个结点。这就是我们反转链表的起始位置。

  • 注意我们要引入两个额外指针,分别称为 tail 和 con。tail 指针指向从链表头起的第m个结点,此结点是反转后链表的尾部,故称为 tail。con 指针指向第 m 个结点的前一个结点,此结点是新链表的头部。

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
61
62
63
64
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def createLink_rearinsert(lista):
head = ListNode(-1)
rear = head
for i in lista:
new_node=ListNode(i)
rear.next=new_node
rear=new_node
return head.next
class Solution:
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""

# Empty list
if not head:
return None

# Move the two pointers until they reach the proper starting point
# in the list.
cur, prev = head, None
while m > 1:
prev = cur
cur = cur.next
m, n = m - 1, n - 1

# The two pointers that will fix the final connections.
tail, con = cur, prev

# Iteratively reverse the nodes until n becomes 0.
while n:
third = cur.next
cur.next = prev
prev = cur
cur = third
n -= 1

# Adjust the final connections as explained in the algorithm
if con:
con.next = prev
else:
head = prev
tail.next = cur
return head

if __name__=="__main__":
a=[1,4,3,2,5,2]
new_a=createLink_rearinsert(a)
a1 = Solution()
p=a1.reverseBetween(new_a,2,4)
list1=[]
while(p!=None):
list1.append(p.val)
#print(p.val)
p=p.next
print(list1)
[1, 2, 3, 4, 5, 2]