time & space trade-off

1. Two Sum

  1. class Solution:
  2. def twoSum(self, nums: List[int], target: int) -> List[int]:
  3. dic = dict()
  4. for idx, num in enumerate(nums):
  5. if target - num in dic:
  6. return [idx, dic[target - num]]
  7. dic[num] = idx
  8. return [-1, -1]
  • 时间复杂度:哈希表 - 图1
  • 空间复杂度:哈希表 - 图2

560. Subarray Sum Equals K

考虑以哈希表 - 图3结尾的子数组的和,逆序遍历哈希表 - 图4保证每个子数组的和都能在哈希表 - 图5时间内求解。
Python使用此解法会TLE。

  1. class Solution:
  2. def subarraySum(self, nums: List[int], k: int) -> int:
  3. num_subarray = 0
  4. for end in range(len(nums)):
  5. array_sum = 0 # 以end为结尾的子数组的和 --> nums[start:end+1]
  6. for start in range(end, -1, -1):
  7. array_sum += nums[start]
  8. if array_sum == k:
  9. num_subarray += 1
  10. return num_subarray
  • 时间复杂度:哈希表 - 图6
  • 空间复杂度:哈希表 - 图7

上述方法可进行时间优化的地方在于,对于每个哈希表 - 图8,能否在哈希表 - 图9时间内找到相应的哈希表 - 图10(或者说是找到相应的子数组数量)?当然,这需要引入额外的空间开销(哈希表)。

  1. 定义哈希表 - 图11哈希表 - 图12之前所有数字的和,则前缀和的公式:哈希表 - 图13
  2. 假设子数组哈希表 - 图14的和恰好等于哈希表 - 图15,则有:哈希表 - 图16
  3. 移项,得到:哈希表 - 图17

综上,考虑以哈希表 - 图18结尾且和为哈希表 - 图19的子数组数量,转化为求前缀和为哈希表 - 图20的数量。

  1. class Solution:
  2. def subarraySum(self, nums: List[int], k: int) -> int:
  3. count = 0
  4. freq = collections.defaultdict(int)
  5. freq[0] = 1
  6. array_sum = 0
  7. for num in nums:
  8. array_sum += num
  9. if array_sum - k in freq:
  10. count += freq[array_sum - k]
  11. freq[array_sum] += 1
  12. return count
  • 时间复杂度:哈希表 - 图21
  • 空间复杂度:哈希表 - 图22

1248. Count Number of Nice Subarrays

1512. Number of Good Pairs

若暴力枚举,时间复杂度哈希表 - 图23
哈希表 - 图24

  1. class Solution:
  2. def numIdenticalPairs(self, nums: List[int]) -> int:
  3. return sum(v*(v-1) // 2 for v in collections.Counter(nums).values() if v > 1)
  • 时间复杂度:哈希表 - 图25
  • 空间复杂度:哈希表 - 图26

128. Longest Consecutive Sequence

  1. class Solution:
  2. def longestConsecutive(self, nums: List[int]) -> int:
  3. num_set = set(nums)
  4. longest_len = 0
  5. for num in num_set:
  6. # 若num-1在集合中,不必重复计算
  7. if num - 1 not in num_set:
  8. current_num = num
  9. current_len = 1
  10. while current_num + 1 in num_set:
  11. current_num += 1
  12. current_len += 1
  13. longest_len = max(longest_len, current_len)
  14. return longest_len
  • 时间复杂度:哈希表 - 图27
  • 空间复杂度:哈希表 - 图28