数据结构之双指针问题(二)

数组:有没有排序;有没有重复;有没有负数

双指针回顾----à

链表:查找中间节点、判断有无环、环的入口、链表中倒数第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-->如果要用双指针:都往后,往中间,都往前,往两边

两个数组:大多数是排好序的

posted @ 2020-02-27 23:05  LinBupt  阅读(282)  评论(0)    收藏  举报