11. Container With Most Water

考虑使用对撞双指针,不断更新面积(可容纳水量):
双指针 - 图1
任意时刻,无论移动双指针 - 图2还是双指针 - 图3,均会使宽度缩小1格,即双指针 - 图4,但考虑高度:

  • 若移动短板双指针 - 图5可能增加
  • 若移动长板双指针 - 图6必定减小不变

故在每个时刻都移动短板,直到两指针相遇,记录最大面积。

  1. class Solution:
  2. def maxArea(self, heights: List[int]) -> int:
  3. l, r = 0, len(heights) - 1
  4. res = (r - l) * min(heights[l], heights[r]) # 初始化
  5. while l < r: # l == r,宽度为0,不必计算
  6. if heights[l] < heights[r]:
  7. l += 1
  8. else:
  9. r -= 1
  10. res = max(res, (r - l) * min(heights[l], heights[r]))
  11. return res
  • 时间复杂度:双指针 - 图7
  • 空间复杂度:双指针 - 图8

15. 3Sum

注意需要返回的是双指针 - 图9而非双指针 - 图10,故可以先对数组进行排序,然后利用双指针缩减搜索空间的办法,降低时间复杂度。
实际上,固定双指针 - 图11对撞双指针双指针 - 图12的搜索,就是转化成了两数之和(有序)

  1. class Solution:
  2. def threeSum(self, nums: List[int]) -> List[List[int]]:
  3. if not nums or len(nums) < 3:
  4. return []
  5. n = len(nums)
  6. nums.sort()
  7. res = []
  8. for k in range(n - 2):
  9. if nums[k] > 0: # 剪枝:数组已经有序,三数之和不可能为'0'
  10. break
  11. if k and nums[k] == nums[k-1]: # 去重:'k > 0'不可缺少
  12. continue # Python中nums[-1]仍有意义
  13. i, j = k + 1, n - 1 # 双指针:缩减搜索空间
  14. while i < j:
  15. sum_3 = nums[k] + nums[i] + nums[j]
  16. if sum_3 < 0:
  17. i += 1
  18. elif sum_3 > 0:
  19. j -= 1
  20. else:
  21. res.append([nums[k], nums[i], nums[j]])
  22. while i < j and nums[i] == nums[i+1]: # 去重
  23. i += 1
  24. i += 1
  25. while i < j and nums[j] == nums[j-1]: # 去重
  26. j -= 1
  27. j -= 1
  28. return res
  • 时间复杂度:双指针 - 图13
  • 空间复杂度:双指针 - 图14

240. Search a 2D Matrix II

看成**BST**,从根节点(二维数组右上角)开始搜索,利用双指针双指针 - 图15双指针 - 图16缩减搜索空间。

  1. class Solution:
  2. def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
  3. m, n = len(matrix), len(matrix[0])
  4. i, j = 0, n - 1
  5. while i < m and j >= 0:
  6. if matrix[i][j] < target:
  7. i += 1
  8. elif matrix[i][j] > target:
  9. j -= 1
  10. else:
  11. return True
  12. return False
  • 时间复杂度:双指针 - 图17
  • 空间复杂度:双指针 - 图18

283. Move Zeroes

双指针 - 图19作为遍历指针,双指针 - 图20指向非零子数组的末尾元素后方,不断交换双指针 - 图21双指针 - 图22达到移动双指针 - 图23的目的。

  1. class Solution:
  2. def moveZeroes(self, nums: List[int]) -> None:
  3. i = 0
  4. for j in range(len(nums)):
  5. if nums[j] != 0:
  6. nums[i], nums[j] = nums[j], nums[i]
  7. i += 1
  • 时间复杂度:双指针 - 图24
  • 空间复杂度:双指针 - 图25