LeetCode—3. Double pointer algorithm—collision pointer, fast and slow pointer and its leetcode problem

introduction

  The double pointer arithmetic is extremely commonly used in array problems. Double pointers are mainly used to traverse the array, and the two pointers point to different elements to complete the task together.

1. Collision pointer

  The collision pointer method, as the name suggests, is that the pointer collides in the middle on both sides. See three

Second, the speed pointer

  The speed indicator can be understood as: a fast runner and a slow runner race on a circular track. At a certain moment, the fast runner will catch up with the slow runner from behind. The fast pointer fast moves two steps at a time, and the slow pointer moves one step at a time, and it will eventually meet at a certain position in the ring (least common multiple)

There are two situations:

1 fast goes to the end of the linked list and returns null
2 fast = slow, the two pointers meet for the first time, the s low pointer starts from the meeting position and the beginning position at the same time, and the meeting position is the ring entrance (you can remember if you don’t understand)

Insert picture description here

Proof:
a = the number of steps from the beginning to the entrance of the ring = 4
b = the number of steps in a ring = 5
fast = 2 * slow = 2
slow = 1 When
meeting, the number of fast steps = the number of slow steps + the number of steps in the n ring ; The number of steps taken by fast is equal to twice the number of steps taken by slow. Therefore, the number of steps taken in
slow is the same as the number of steps in the loop fast = slow + nb => slow = nb

Three, LeetCode—167

  Given an ordered integer array and an integer target, look for two elements in it and make the sum of the target. Returns the indexes of these two numbers.

Example: nums=[2,7,11,15], target=9
Output: [1,2]

  • What if there is no solution? Guaranteed solution
  • What if there are multiple solutions? Return any solution

Note:

Is 3,3+3+3=9 in nums?
Index problem, whether to start from 1 or from 0

Solution 1:
Violent solution, double traversal, time degree is O(n^2), easy to time out ! ! !

class Solution:
    def findTwosum(self, num, target):
        """
        在有序数组中,找到两数和为标签
        :param num:
        :param target:
        :return:
        """
        return self.violentSolution(num, target)

    def violentSolution(self, num, target):
        length = len(num)
        # 双循环
        for i in range(length):
            for j in range(length):
                if num[i] + num[j] == target:
                    return [i, j]


def main():
    num = [2, 3, 5, 7, 9, 10]
    target = 9
    s = Solution()
    solution = s.findTwosum(num, target)
    print('返回索引为', solution)


if __name__ == '__main__':
    main()

Solution 2: The
brute force solution does not make full use of the nature of the original array (ordered), so we should think of using binary search, and its time complexity is O(nlogn).

Binary search is also called half search. The advantage is that the number of comparisons is small, the search speed is fast, and the average performance is good; the disadvantage is that the table to be looked up is required to be an ordered list, and it is difficult to insert and delete. Therefore, the binary search method is suitable for searching frequently ordered lists that do not change frequently.

The principle of binary search: First, suppose the elements in the table are arranged in ascending order. Compare the keywords recorded in the middle position of the table with the search keywords. If the two are equal, the search is successful; otherwise, use the middle position records to divide the table into front and back For the two sub-tables, if the key recorded in the middle position is greater than the search key, the previous sub-table is further searched, otherwise the latter sub-table is further searched. Repeat the above process until a record that meets the conditions is found, and the search is successful, or until the sub-table does not exist, the search is unsuccessful at this time.

class Solution:
    def findTwosum(self,numbers,target):
        """
        二分查找
        :param num: 数组
        :param target: 值
        :return: 返回索引
        """
        return self.binary_search(numbers,target)

    def binary_search(self,numbers,target):
        n = len(numbers)
        for i in range(n):
            low, high = i + 1, n - 1
            while low <= high:
                mid = (low + high) // 2
                if numbers[mid] == target - numbers[i]:
                    return [i + 1, mid + 1]
                elif numbers[mid] > target - numbers[i]:
                    high = mid - 1
                else:
                    low = mid + 1

def main():
    num = [2, 7, 11, 15]
    target = 9
    s = Solution()
    solution = s.findTwosum(num, target)
    print('索引为', solution)


if __name__ == '__main__':
    main()

Solution 3:
  Collision pointer method, as the name suggests, is that the pointer hits the middle on both sides. Space complexity O(1)

class Solution:
    def findTwosum(self, num, target):
        return self.collision_pointer(num, target)

    def collision_pointer(self, num, target):
        """
        对撞指针
        :param num: 有序数组
        :param target: 标签
        :return: 返回索引
        """
        i, j = 0, len(num) - 1
        while i < j:
            if num[i] + num[j] == target:
                break
            elif num[i] + num[j] > target:
                j -= 1
            else:
                i += 1
        if num[i] + num[j] == target:
            return [i + 1, j + 1]
        else:
            print('List is not solution!!!')


def main():
    num = [2, 7, 11, 15]
    target = 9
    s = Solution()
    solution = s.findTwosum(num, target)
    print('索引为', solution)


if __name__ == '__main__':
    main()

Other problems using colliding pointers

125. Determine whether it is a palindrome string

Given a string, only look at the numbers and letters in it, ignoring the case, and judge whether the string is a palindrome string

class Solution:
    def isPalindrome(self, s):
        return self.pointer(s)

    # 对撞指针解回文字符串
    def pointer(self, s):
        s = s.lower()
        # 去掉除字符串与数字外的其他
        s = [i for i in s if i.isalpha() or i.isnumeric()]
        s = "".join(s)
        i, j = 0, len(s) - 1
        while i < j:
            if s[i] == s[j]:
                i += 1
                j -= 1
            else:
                return False
        return True


def main():
    s = "A man, a plan, a canal: Panama"
    ss = Solution()
    solution = ss.isPalindrome(s)
    print(solution)


if __name__ == '__main__':
    main()

344. Reversed string

Given a string, return the reversed string of this string

class Solution:
    def reverseString(self, s) :
        return self.pointer(s)

    def pointer(self,s):
        i,j = 0,len(s)-1
        while i < j:
            s[i],s[j] = s[j],s[i]
            i += 1
            j -= 1
        return s

def main():
    s = ["h","e","l","l","o"]
    ss = Solution()
    solution = ss.reverseString(s)
    print(solution)

if __name__ == '__main__':
    main()

345. Flip the vowels in the string

Given a string, flip the vowels in the string

# 元音字母有'a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U'
class Solution:
    def reverseVowels(self, s):
        return self.pointer(s)

    def pointer(self, s):
        s = [i for i in s]
        # print(s)
        i, j = 0, len(s) - 1
        while i < j:
            if s[i] not in ['a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U']:
                i += 1
            elif s[j] not in ['a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U']:
                j -= 1
            else:
                s[i], s[j] = s[j], s[i]
                i += 1
                j -= 1
        s = ''.join(s)
        return s


def main():
    s = "hello"
    ss = Solution()
    solution = ss.reverseVowels(s)
    print(solution)


if __name__ == '__main__':
    main()

Four, LeetCode—142

142. Circular Linked List II

Given a linked list, return the first node in the ring of the linked list. If the linked list has no rings, null is returned. In order to represent the rings in a given linked list, we use the integer pos to indicate the position where the end of the linked list is connected to the linked list (the index starts from 0). If pos is -1, it means that there is no ring in the linked list. pos is only used to identify the case of the ring, and will not be passed to the function as a parameter.
Note: It is not allowed to modify the given linked list

Insert picture description here

Input: head = [3,2,0,-4], pos = 1
Output: Return the linked list node with index 1
Explanation: There is a ring in the linked list, and its tail is connected to the second node

  If we use a Set to save the visited nodes, we can traverse the entire linked list and return the first duplicate node. Space complexity is O(n)

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

Added condition: space complexity is O (1)

Linked list knowledge

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        fast,slow = head,head
        while fast != None:
            fast = fast.next
            if fast == None:
                break
            fast = fast.next
            slow = slow.next
            if slow == fast:
                break
        # 链表中没有环
        if fast == None:
            return None
        p1,p2 = slow,head

        while p1 != p2:
            p1 = p1.next
            p2 = p2.next
        return p1

Guess you like

Origin blog.csdn.net/weixin_46649052/article/details/114419116