哈希表(Hash Table)作为数据结构中的瑞士军刀,在算法面试和实际工程中都有着举足轻重的地位。今天我将通过四道经典力扣题目,带你深入掌握哈希表在不同场景下的应用技巧。这些题目看似简单,但其中蕴含的优化思路和边界条件处理,正是区分普通程序员和算法高手的试金石。
给定四个整数数组A、B、C、D,我们需要统计有多少个元组(i,j,k,l)满足A[i] + B[j] + C[k] + D[l] = 0。最直观的暴力解法是四重循环,时间复杂度高达O(N^4),当N=500时,这将导致625亿次运算,显然不可行。
关键突破点在于将问题转化为两组两数之和的问题:
这种"分治+哈希"的思路将时间复杂度从O(N^4)降低到O(N^2),空间复杂度为O(N^2)。
python复制def fourSumCount(nums1, nums2, nums3, nums4):
hashmap = {}
# 统计前两组元素的和
for n1 in nums1:
for n2 in nums2:
sum_ab = n1 + n2
hashmap[sum_ab] = hashmap.get(sum_ab, 0) + 1
count = 0
# 查询后两组元素的相反数和
for n3 in nums3:
for n4 in nums4:
target = - (n3 + n4)
count += hashmap.get(target, 0)
return count
关键细节:使用hashmap.get(key, default)方法可以避免键不存在的KeyError,保持代码简洁。
给定两个字符串ransomNote和magazine,判断ransomNote是否能由magazine中的字符组成。注意:
python复制def canConstruct(ransomNote, magazine):
if len(ransomNote) > len(magazine):
return False
char_count = [0] * 26 # 使用数组替代哈希表,效率更高
for c in magazine:
char_count[ord(c) - ord('a')] += 1
for c in ransomNote:
index = ord(c) - ord('a')
if char_count[index] == 0:
return False
char_count[index] -= 1
return True
虽然可以使用哈希法解决三数之和问题,但面临两个主要挑战:
python复制def threeSum(nums):
nums.sort()
result = []
n = len(nums)
for i in range(n - 2):
if nums[i] > 0: # 提前终止
break
if i > 0 and nums[i] == nums[i-1]: # 外层去重
continue
left, right = i + 1, n - 1
while left < right:
total = nums[i] + nums[left] + nums[right]
if total < 0:
left += 1
elif total > 0:
right -= 1
else:
result.append([nums[i], nums[left], nums[right]])
# 内层去重
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
return result
去重关键:在外层循环跳过相同元素,在内层找到解后也要跳过相同元素
四数之和可以看作在三数之和的基础上再加一层循环,核心思路:
python复制def fourSum(nums, target):
nums.sort()
n = len(nums)
result = []
for i in range(n - 3):
# 一级剪枝
if nums[i] > target and nums[i] > 0 and target > 0:
break
if i > 0 and nums[i] == nums[i-1]:
continue
for j in range(i + 1, n - 2):
# 二级剪枝
if nums[i] + nums[j] > target and target > 0:
break
if j > i + 1 and nums[j] == nums[j-1]:
continue
left, right = j + 1, n - 1
while left < right:
total = nums[i] + nums[j] + nums[left] + nums[right]
if total == target:
result.append([nums[i], nums[j], nums[left], nums[right]])
# 内层去重
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
elif total < target:
left += 1
else:
right -= 1
return result
经过这四道题目的训练,我们可以总结出以下选择策略:
使用哈希表的场景:
使用双指针的场景:
在实际面试中,建议先分析问题特点,再选择合适的方法。有时候可以先提出哈希解法,再优化为双指针解法,展示思维过程。