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
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:
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
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:
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:
The fast and slow pointer method is relatively complicated:
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+k1⋅b+c)⋅2=a+k2⋅b+c a=(k2−2⋅k1)⋅b−c
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:
206. Reverse Linked List
Problem Description
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:
The recursive method is a bit troublesome to understand, you can refer to the animation in the solution below:
Problem solution - recursive animation
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:
92. Reverse Linked List II
Problem Description
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:
24. Swap Nodes in Pairs (two-two exchange nodes in the linked list)
Problem Description
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: