题目:
题目链接: https://leetcode-cn.com/problems/reverse-linked-list-ii/
解题思路:
方法一:数组 + 新链表
因为题目中并没有要求必须使用原节点,所以只需要将对应的节点值进行交换就行
所以比较简单的方法,就是将所有节点中的值,放到一个数组中,将对应值进行交换,然后生成新链表
数组值交换的方法为:
- 交换m和n下标对应的值
- m向右移,n向左移,继续交换值,直到m >= n为止
图示如下:
方法二:递归
如果利用递归,其实可以对单向链表实现类似方法一中的功能,图示流程如下:
变量:
- left : 左边需要交换值的节点,全局变量
- right : 右边需要交换值的节点,递归变量
- stop: 是否停止递归,全局变量
逻辑图示如下:
开始时,每次递归,如果left如果没移动到开始节点,每次将left向右移动1;right如果没移动到结束节点,向右移动一
此时停止移动left和right,交换left和right的值,并将全局变量left向右移动1,返回上一层递归
因为right是递归变量,并且刚刚只是交换了值,并没有修改节点的顺序
所以在返回上一层递归时,实现了类似双向链表prev的功能,使得right回退到了前一个节点,如下图所示:
此时再次交换值,并向右移动left,返回上一层递归:
此时发现left和right指向同一个节点,修改全局变量stop为True,停止上层递归的所有交换值操作,完成值的交换
代码实现:
方法一:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
val_lst = []
while head:
val_lst.append(head.val)
head = head.next
m -= 1
n -= 1
while m < n:
val_lst[m], val_lst[n] = val_lst[n], val_lst[m]
m += 1
n -= 1
dummy = ListNode(0)
new_head = dummy
for val in val_lst:
new_head.next = ListNode(val)
new_head = new_head.next
return dummy.next
方法二:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
if not head or m >= n:
return head
left, right = head, head
stop = False
def reverse_help(right, m, n):
nonlocal left, stop
if n <= 1:
return
right = right.next
if m > 1:
left = left.next
reverse_help(right, m - 1, n - 1)
if not stop:
left.val, right.val = right.val, left.val
left = left.next
if left is right or left.next is right:
stop = True
reverse_help(right, m, n)
return head