Article Directory
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)
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
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)
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