LeetCode Problem Set: Linked List (1)

This article introduces the problem of linked list in LeetCode problem set.

Other LeetCode questions about linked lists:
LeetCode Problem Set: Linked List (2)
LeetCode Problem Set: Linked List (3)


141. Linked List Cycle


Problem Description

LeetCode 141 Problem Description I
LeetCode 141 Problem Description II

ideas and code


This question is solved by following the train of thought of fast and slow pointers.

code show as below:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        fast, slow = head, head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                return True

        return False

running result:
LeetCode 141 running effect

The above code is a double-speed catch-up. In fact, the speed of the fast pointer can be any multiple of the slow pointer.

Code for triple speed:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        fast, slow = head, head
        while fast and fast.next and fast.next.next:
            fast = fast.next.next.next
            slow = slow.next
            if fast == slow:
                return True

        return False

Code for quadruple speed:

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        fast, slow = head, head
        while fast and fast.next and fast.next.next and fast.next.next.next:
            fast = fast.next.next.next.next
            slow = slow.next
            if fast == slow:
                return True

        return False

There is no significant difference in performance.


142. Linked List Cycle II


Problem Description

LeetCode 142 Problem Description I
LeetCode 142 Problem Description II

ideas and code


Refer to the official question solution, there are two methods for this question: hash table and fast and slow pointer.

LeetCode 142 Official Solution

The hash table approach is relatively easy to understand:

LeetCode 142 Official Solution 1
LeetCode 142 Official Solution 2

code show as below:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        set_visit = set()
        set_visit.add(head)
        while head:
            if not head.next:
                return None

            if head.next in set_visit:
                return head.next
            else:
                set_visit.add(head.next)
                head = head.next

running result:
LeetCode 142 Running Effect 1

The fast and slow pointer method is relatively complicated:

LeetCode 142 Fast and slow pointer method

The speed of the fast pointer is twice that of the slow pointer. When the fast and slow pointers meet, a new pointer is defined to point to the starting point. The new pointer and the slow pointer move forward at the same time at the same speed, and finally they meet at the loop entry point. The mathematical derivation is as follows:

When the fast and slow pointers meet, the slow pointer rotates k 1 k_1 in the ringk1circle, the fast pointer turns k 2 k_2k2For example:
( a + k 1 ⋅ b + c ) ⋅ 2 = a + k 2 ⋅ b + c a = ( k 2 − 2 ⋅ k 1 ) ⋅ b − c (a + k_1 \cdot b + c) \cdot 2 = a + k_2 \cdot b + c \\ \ \\ a = (k_2 - 2 \cdot k_1) \cdot b - c(a+k1b+c)2=a+k2b+c a=(k22k1)bc

code show as below:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        fast, slow = head, head
        while fast and slow:
            if fast.next:
                fast = fast.next.next
            else:
                return None
            slow = slow.next

            if fast == slow:
                tmp = head
                while tmp != slow:
                    tmp = tmp.next
                    slow = slow.next
                return tmp

        return None

running result:
LeetCode 142 Operation Effect 2


206. Reverse Linked List


Problem Description

LeetCode 206 Problem Description I
LeetCode 206 Problem Description II

ideas and code


There are two methods for this problem, iterative and recursive.

The idea of ​​the iterative method is relatively simple. Define a pre node to represent the previous node, and iterate in a loop.

code show as below:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head

        pre = None  # initialise pre
        while head:
            tmp = head.next  # store head.next since head will change soon
            head.next = pre  # change head.next to pre
            pre = head  # pre move to head
            head = tmp  # head move to head.next using tmp

        return pre

running result:
LeetCode 206 Running Effect 1

The recursive method is a bit troublesome to understand, you can refer to the animation in the solution below:

Problem solution - recursive animation

LeetCode linked list attention

code show as below:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        def rec(node: ListNode):
            if not node or not node.next:
                return node

            node_new = rec(node=node.next)  # deepest invocation: return the tail as head after reversing
            node.next.next = node  # next of node.next point to current node
            node.next = None  # next of node set to None, will reset during pre recursion
            return node_new

        return rec(node=head)

running result:
LeetCode 206 Running Effect 2


92. Reverse Linked List II


Problem Description

LeetCode 92 Problem Description I
LeetCode 92 Problem Description II

ideas and code


This question is a variant of the previous question. You can call the inversion function of the previous question to complete the inversion in the segment. For the head and tail parts outside the segment, you can splice them to the front and back of the reversed segment.

code show as below:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
        def reverse_linked_list(head: ListNode):  # LeetCode 206, iteration type
            pre = None
            cur = head
            while cur:
                next = cur.next
                cur.next = pre
                pre = cur
                cur = next

        # use dummy node to store the head
        dummy = ListNode(-1)
        dummy.next = head
        pre = dummy

        # get the node before the left node
        for _ in range(left - 1):
            pre = pre.next

        # get the right node
        right_node = pre
        for _ in range(right - left + 1):
            right_node = right_node.next

        left_node = pre.next  # the left node
        curr = right_node.next  # next node of the right node

        # cut off the period
        pre.next = None
        right_node.next = None

        # reverse the period
        reverse_linked_list(left_node)

        # join back to the head and tail
        pre.next = right_node
        left_node.next = curr

        return dummy.next

running result:
LeetCode 92 running effect


24. Swap Nodes in Pairs (two-two exchange nodes in the linked list)


Problem Description

LeetCode 24 Problem Description I
LeetCode 24 Problem Description II

ideas and code


The idea of ​​this question is similar to the previous two questions. Define two pointers (nodes), reverse each pair of nodes in turn, and then move the pointer forward by two bits, and iterate in a loop.

code show as below:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        dummy = ListNode(val=-1)
        dummy.next = head
        pre = dummy
        while pre.next and pre.next.next:
            first, second = pre.next, pre.next.next
            first.next = second.next
            second.next = first
            pre.next = second
            pre = first  # pre, move 2 steps to next couple

        return dummy.next

running result:
LeetCode 24 running effect

Guess you like

Origin blog.csdn.net/Zhang_0702_China/article/details/121207340