数据结构之双指针问题(二)
数组:有没有排序;有没有重复;有没有负数
双指针回顾----à
链表:查找中间节点、判断有无环、环的入口、链表中倒数第k个元素、归并排序、分区/快排、查找第k个最大元素
一、Merge Two Sorted Array into One
You are given two sorted arrays, A and B, and A has a large enough buffer at the end to hold B. Write a method to merge B into A in sorted order
1 def merge(nums1, m, nums2, n): 2 while m > 0 and n > 0: 3 if nums1[m-1] > nums2[n-1]: 4 nums1[m+n-1] = nums1[m-1] 5 m = m - 1 6 else: 7 nums1[m+n-1] = nums2[n-1] 8 n = n - 1 9 if n > 0: 10 nums1[:n] = nums2[:n] 11 return nums1 12 nums1 = [1, 2, 3, 0, 0, 0, 0] 13 m = 3 14 nums2 = [0, 2, 5, 6] 15 n = 4 16 print(merge(nums1, m, nums2, n))
二、Minimum Difference Between Two Sorted Arrays
Given two arrays sorted in ascending order, find the absolute minimum difference between any pair of elements |a-b| such that a is from one array and b is from another array.
1 import sys 2 def printClosest(nums1, nums2): 3 m = len(nums1) 4 n = len(nums2) 5 diff = sys.maxsize 6 p1 = 0 7 p2 = 0 8 while p1 < m and p2 < n: 9 if abs(nums1[p1]-nums2[p2]) < diff: 10 diff = abs(nums1[p1] - nums2[p2]) 11 if nums1[p1] > nums2[p2]: 12 p2 += 1 13 else: 14 p1 += 1 15 return diff 16 nums1 = [1, 2, 3, 4, 5, 9, 10] 17 nums2 = [6, 7, 8, 10, 11] 18 print(printClosest(nums1, nums2))
补充:两个有序数组的交集
如果是两个相差比较大的数组:从一个数组挨次取元素,去另一个数组二分查找。nlogm
如果是两个差不多大的数组:双指针 m+n
三、Continuous Maximum Subarray
Given an array having N positive integers, find the contiguous subarray having sum as great as possible, but not greater than M.
1 def continuousMax(nums, target): 2 i = j = 0 3 res = resp = resq = 0 4 while j < len(nums): 5 sum = 0 6 for k in range(i, j+1): 7 sum += nums[k] 8 if sum <= target: 9 if res < sum: 10 res = sum 11 resp = i 12 resq = j 13 j += 1 14 else: 15 i += 1 16 17 return (resp, resq) 18 nums = [4, 7, 12, 1, 2, 3, 6] 19 print(continuousMax(nums, 18))
1 from itertools import accumulate # O(n) 2 def max_subarray(nums, ceiling): 3 cum_sum = [0] 4 cum_sum = cum_sum + nums 5 cum_sum = list(accumulate(cum_sum)) 6 l = 0 7 r = 1 8 maximum = 0 9 while l < len(cum_sum): 10 while r < len(cum_sum) and cum_sum[r] - cum_sum[l] <= ceiling: 11 r += 1 12 if cum_sum[r-1] - cum_sum[l] > maximum: 13 maximum = cum_sum[r-1] - cum_sum[l] 14 pos = (1, r-2) 15 l += 1 16 return pos
四、Majority Element
Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
1 from collections import Counter # O(n) 空O(n) 2 def majority(nums): 3 dic = Counter() 4 res = [] 5 for num in nums: 6 if num in dic: 7 dic[num] += 1 8 else: 9 dic[num] = 1 10 for key, values in dic.items(): 11 if dic[key] >= len(nums) // 2: 12 res.append(key) 13 return res 14 nums = [1, 2, 3, 4, 6, 6, 6, 6, 6] 15 print(majority(nums))
排序:O(nlogn) O(1)
# Boyer-Moore Voting Algorithm # O(n) O(1) def majority(nums): result = count = 0 for i in nums: if count == 0: result = i count += 1 elif result == i: count += 1 else: count -= 1 return result
进阶:
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.
字典/排序
摩尔:刚才给一个candidate,现在给两个candidate。
1 # 摩尔投票算法 2 3 def majority(nums): 4 result = count = 0 5 for i in nums: 6 if count == 0: 7 result = i 8 count += 1 9 elif result == i: 10 count += 1 11 else: 12 count -= 1 13 return result 14 def majority1(nums): 15 n1 = n2 = None 16 c1 = c2 = 0 17 for num in nums: 18 if n1 == num: 19 c1 += 1 20 elif n2 == num: 21 c2 += 1 22 elif c1 == 0: 23 n1 = num 24 c1 = 1 25 elif c2 == 0: 26 n2 = num 27 c2 = 1 28 else: 29 c1 -= 1 30 c2 -= 1 31 size = len(nums) 32 return [n for n in (n1, n2) 33 if n is not None and nums.count(n) > size / 3] 34 print(majority1([1, 1, 1, 1, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9]))
五、Sort Color
荷兰国旗
Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
排序:nlogn
计数排序:n
1 # 计数排序-->有范围且有大量重复,O(n) 2 def countSort(nums): 3 res = [[], [], []] 4 for num in nums: 5 if num == 0: 6 res[0].append(num) 7 elif num == 1: 8 res[1].append(num) 9 else: 10 res[2].append(num) 11 return res 12 def sortColors(nums): 13 count = [0] * 3 14 for num in nums: 15 count[num] += 1 16 i = 0 17 for j in range(3): 18 for _ in range(count[j]): 19 nums[i] = j 20 i += 1 21 return nums 22 print(countSort([0, 0, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 1, 0])) 23 print(sortColors([0, 0, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 1, 0]))
1 def sortColors(nums): # l-->最后一个0的后面一个, i-->当前探索的点, r-->第一个2的前面一个 2 i, l, r = 0, 0, len(nums) - 1 3 while i <= r: 4 if nums[i] == 0: 5 nums[i], nums[l] = nums[l], nums[i] 6 i, l = i + 1, l + 1 7 elif nums[i] == 2: 8 nums[i], nums[r] = nums[r], nums[i] 9 r -= 1 10 else: 11 i += 1 12 return nums 13 14 def sortColor(nums): 15 l = 0 #最后一个0结尾的后面一个 16 m = 1 #当前正在检测的点 17 r = len(nums) - 1 #第一个2的前面一个 18 while m < r: 19 if nums[m] == 0: 20 nums[l], nums[m] = nums[m], nums[l] 21 l += 1 22 if nums[l] == nums[m]: 23 m += 1 24 elif nums[m] == 2: 25 nums[m], nums[r] = nums[r], nums[m] 26 r -= 1 27 if nums[m] == nums[r]: 28 m -= 1 29 else: 30 m += 1 31 return nums 32 33 print(sortColor([0, 0, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 1, 0])) 34 print(sortColors([0, 0, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 1, 0]))
六、Find K Closest Elements
Given a sorted array, two integers k and x, find the k closest elements to x in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred.
排序:o(n)+O(nlogn)
heap:klogk + n
1 #双指针 2 def findKClosest(nums, target): 3 left = 0 4 right = len(nums) - 1 5 flag = False 6 while left + 1 < right: 7 mid = (left + right) // 2 8 if nums[mid] > target: 9 right = mid 10 elif nums[mid] == target: 11 flag = True 12 break 13 else: 14 left = mid 15 if not flag: 16 mid = left if target - nums[left] <= nums[right] - target else right 17 count = 1 18 res = [nums[mid]] 19 rmid = mid + 1 20 lmid = mid - 1 21 while count < 5: 22 if nums[rmid] - target < target - nums[lmid]: 23 res.append(nums[rmid]) 24 rmid += 1 25 count += 1 26 else: 27 res.append(nums[lmid]) 28 lmid -= 1 29 count += 1 30 return res
内置的bisect!
1 import bisect 2 def findKClosestElements(nums, k, x): 3 left = right = bisect.bisect_left(nums, x) 4 if left == 0: 5 return nums[:k] 6 if right == len(nums): 7 return nums[-k:] 8 while right - left < k: 9 if x - nums[left] <= nums[right] - x: 10 left -= 1 11 else: 12 right += 1 13 return nums[left:right] 14 num = [1, 20, 22, 23, 24, 25, 26] 15 print(findKClosestElements(num, 6, 19))
七、Container With Most Water
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
1 # brute force O(n**2) 2 def maxArea(height): 3 res = 0 4 for i in range(len(height)): 5 for j in range(i+1, len(height)): 6 res = max(res, min(height[i], height[j])*(j-i)) 7 return res
1 # 双指针 2 def maxArea(height): 3 left = 0 4 right = len(height) - 1 5 res = 0 6 while left < right: 7 res = max(res, (right - left) * min(height[left], height[right])) 8 if height[left] < height[right]: 9 left += 1 10 else: 11 right -= 1 12 return res
总结:
一个数组:需不需要sort-->如果要用双指针:都往后,往中间,都往前,往两边
两个数组:大多数是排好序的

浙公网安备 33010602011771号