天天看点

leetcode92. 反转链表 II

92. 反转链表 II

https://leetcode-cn.com/classic/problems/reverse-linked-list-ii/

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

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

示例:

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

方法1

from linked_list.list_op import create_list, print_list


class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution_0(object):
    """ 思路
        1. 截取出需要翻转的部分
            1.1 记录下需要翻转的节点m,以及m的前一个节点
            1.2 需要翻转的链表尾部节点n以及n的下一个节点
        2. 翻转后接入到来的链表中
    """

    def reverseBetween(self, head, m, n):
        if head is None:
            return head

        pre = None
        cur = head
        i = 0
        while i < m - 1:
            pre = cur
            cur = cur.next
            i += 1
        last_node = cur

        tmp = cur
        while i < n - 1:
            cur = cur.next
            i += 1
        post_node = cur.next

        new_root = self.reverse_helper(tmp, 0, n - m + 1)
        # 需要判断pre是不是为None, 也就是判断是不是从链表的第一个节点就开始翻转了
        if pre is not None:
            pre.next = new_root
        else:
            head = new_root
        last_node.next = post_node
        return head

    def reverse_helper(self, root, cur_count, total):
        if cur_count + 1 == total:
            return root
        node = self.reverse_helper(root.next, cur_count + 1, total)
        root.next.next = root
        root.next = None
        return node

           

方法2

class Solution(object):
    """ 思路
        1. 如果m==1,那么这个题目就是翻转一个链表的前n个节点
        2. 如果m!=1, 假设原始链表的头结点是C,首先找到第m-1个节点(假设为A)保存下来,
        然后翻转以第m个节点为链表头的链表(返回新的头节点,假设为B)
        之后A.next = B就完成了,注意要返回原来的头结点
    """
    succesor = None

    def reverseBetween(self, head, m, n):
        if head is None:
            return head
        if m == 1:
            new_root = self.reverse_top_n(head, n)
            return new_root
        else:
            cur = head
            i = 2
            while i < m:
                cur = cur.next
                i += 1
            tmp_root = self.reverse_top_n(cur.next, n - m + 1)
            cur.next = tmp_root
            return head


    # 辅助函数,翻转一个链表的前n个节点
    def reverse_top_n(self, head, num):
        assert num >= 0, "Value error"
        if num == 1:
            self.succesor = head.next
            return head

        node = self.reverse_top_n(head.next, num - 1)
        head.next.next = head
        head.next = self.succesor
        return node




if __name__ == '__main__':
    nums = [1, 2, 3, 4, 5, 6]
    head = create_list(nums)
    print_list(head)
    sol = Solution()
    new_head = sol.reverseBetween(head, 1, 4)
    print_list(new_head)