[leetcode-python brush question] Double pointer (fast and slow pointer)

141. Ring Linked List (easy)

topic

Given a linked list, determine whether there is a cycle in the linked list.

If there is a node in the linked list that can be reached again by continuously tracking the next pointer, then there is a cycle in the linked list. To represent a cycle in a given list, we use the integer pos to denote the position in the list where the tail of the list joins (indexes start at 0). If pos is -1, there are no cycles in the list. Note: pos is not passed as a parameter, it is just to identify the actual situation of the linked list.

Returns true if there is a cycle in the linked list. Otherwise, returns false.

Source: LeetCode
Link: https://leetcode-cn.com/problems/linked-list-cycle
The copyright belongs to LeetCode. For commercial reprints, please contact the official authorization, for non-commercial reprints, please indicate the source.

V1 (fast and slow pointer)

Using the fast and slow pointers, the slow pointer moves backward one position at a time, and the fast pointer moves backward two positions at a time. If there is a ring, there must be a time when the fast and slow pointers are equal.
The space complexity of the algorithm in this case is O(1), using only the extra space of two pointers. The time complexity is O(N), where N is the number of nodes in the linked list.

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

Result:
insert image description here
What went wrong:

  1. Originally, the judgment conditions in lines 3 and 4 were not added, and an error was reported:
    insert image description here
    Notice: not headand not head.nextBoth judgment conditions are required, the former is to prevent the occurrence of an empty linked list, and the latter is to prevent the occurrence of a linked list with only one element and no ring under the premise of a non-empty linked list.
  2. The original judgment condition in line 7 is if not fast, and the latter judgment condition is missing, and an error is reported:
    insert image description here

Code when written and tested locally:

# 定义结点
class Node(object):
    def __init__(self, item):
        self.item = item
        self.next = None

# 定义单链表
class SingleLinkList(object):
    def __init__(self):
        self._head = None  # 首地址指针head

def hasCycle(head):
    if not head or not head.next:
        return False
    slow, fast = head, head.next
    while slow != fast:
        if not fast or not fast.next:
            return False
        slow = slow.next
        fast = fast.next.next
    return True

link_list = SingleLinkList()
node1 = Node(3)
node2 = Node(2)
node3 = Node(0)
node4 = Node(-4)
link_list._head = node1
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node2
print(hasCycle(node1))

V2 (hash table)

Put all the seen elements into the seen collection, and judge whether the next element appears in the seen.

def hasCycle(head):
    seen = set()
    while head:
        if head not in :
            seen.add(headseen)
            head = head.next
        else:
            return True
    return False

result:
insert image description here

  • Time complexity: O(N), where N is the number of nodes in the linked list. In the worst case we need to traverse each node once.
  • Space complexity: O(N), where N is the number of nodes in the linked list. Mainly the overhead of the hash table, in the worst case we need to insert each node into the hash table once.

283. Moving Zero (easy)

topic

Given an array nums, write a function to move all 0s to the end of the array while maintaining the relative order of the nonzero elements.

V1

Two pointers i, j, i is used to find 0, j is used to find the first non-zero element after i, and then exchange positions.

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        i = 0
        while i < len(nums) - 1:
            if nums[i] == 0:
                break
            i += 1
        if i == len(nums) - 1:
            return nums
        while i < len(nums) - 1:
            j = i + 1
            while j < len(nums):
                if nums[j] != 0:
                    break
                j += 1
            if j == len(nums):
                break
            nums[i], nums[j] = nums[j], nums[i]
            i += 1
            while nums[i] != 0:
                i += 1
        return nums

Result:
insert image description here
It can be seen that it is very time consuming.

v2

There are also two pointers, one pointing down from the beginning to ensure that the pointed positions are all non-zero, and the other is used to find all non-zero items.

class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        i = j = 0
        while j < len(nums):
            if nums[j] != 0:
                nums[i], nums[j] = nums[j], nums[i]
                i += 1
            j += 1

result:
insert image description here

27. Remove elements (easy)

topic

Given an array nums and a value val, you need to remove all elements whose value is equal to val in place, and return the new length of the removed array.

Don't use extra array space, you have to use only O(1) extra space and modify the input array in-place.

The order of elements can be changed. You don't need to consider elements in the array beyond the new length.

Source: LeetCode
Link: https://leetcode-cn.com/problems/remove-element
Copyright belongs to LeetCode Network. For commercial reprints, please contact the official authorization, for non-commercial reprints, please indicate the source.

V1

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i = 0
        while i < len(nums):
            if nums[i] == val:
                del nums[i]
            else:
                i += 1
        return len(nums)

result:
insert image description here

v2

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        index = 0
        for i in nums:
            if i != val:
                nums[index] = i
                index += 1
        return index

result:
insert image description here

V3

double pointer.

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i, j = 0, len(nums) # 注意j的初始值
        while i < j:
            if nums[i] == val:
                nums[i] = nums[j-1]
                j -= 1
            else:
                i += 1
        return i

result:
insert image description here

26. Remove duplicates in sorted array (easy)

topic

Given an ordered array nums, please delete repeated elements in place so that each element appears only once, and return the new length of the deleted array.

Don't use extra array space, you have to modify the input array in-place and do so using O(1) extra space.

Source: LeetCode
Link: https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
The copyright belongs to Leetcode Network. For commercial reprints, please contact the official authorization, for non-commercial reprints, please indicate the source.

V1

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        if len(nums) <= 1:
            return len(nums)
        i, index = 1, 1
        while i < len(nums):
            if nums[i] not in nums[:index]:
                nums[index] = nums[i]
                index += 1
            i += 1
        return index

result:
insert image description here

v2

After reading other people's answers, I found out that I missed a key information when I read the question:ordered array

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        if not nums:
            return 0
        i, j = 0, 0
        while j < len(nums):
            if nums[i] != nums[j]:
                i += 1
                nums[i] = nums[j]
            j += 1
        return i + 1

result:
insert image description here

80. Remove Duplicates in Sorted Array II(medium)

topic

Given an ordered array nums, please delete repeated elements in place, so that each element appears at most twice, and return the new length of the deleted array.

Don't use extra array space, you have to modify the input array in-place and do so using O(1) extra space.

Source: LeetCode
Link: https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii
The copyright belongs to Leetcode.com. For commercial reprints, please contact the official authorization, for non-commercial reprints, please indicate the source.

V1

I failed to write it myself, and it is in the reference solution.

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        i = 2
        for j in nums[2:]:
            if nums[i-2] != j:
                nums[i] = j
                i += 1
        return i

Result:
insert image description here
At the beginning, I always thought about counting the number of occurrences of the value pointed by the pointer, but I didn't expect to compare it directly with the previous two values.

Guess you like

Origin blog.csdn.net/zylooooooooong/article/details/119704903
Recommended