hashtable 是 实现算法 时常用的一种 有效数据结构,它的 高效性 在于,在需要快速插入和查询时,无论有多少个item, 它的操作时间总是接近于O(1)。
原因在于 hashtable 是散列的,它的key-value 几乎总是 一一对应的,而key 通常被我们称之为 hashcode。
设计hashtable的 关键在与 hashcode的 function 设计,即 在k和v之间所存在的对应关系,使得 v = f(k) ,该 f 称为 hash 函数。
在实际应用中,如何将hashcode 设计为范围尽可能快速有效地指向我们需要解决的值 是hashtable有效与否的关键。而且, 当发生hash冲突时 如何处理 也要取决于我们需求。
所谓的hash冲突指的是,当 key 的集合很大时,key值不同的元素可能会映射到同一个地址上去,即 key1 != key2, 但 f(key1) = f(key2)。
本文主要涉及 在小算法中 hash函数的设计。
最近在LeetCode遇到几个算法题, 细细想来 hashtable 是个不错的解决方法。
1. 2 sum
给出一个列表,返回和是指定的数的两个元素的下标。
如 : 给出 nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
如果想用hashtable解决这个问题, 我们将hash函数设计为 f(k) = nums.index(k) ,k为nums中的元素, value 为 k 在nums 中的索引,这样就能有效地找到k的同时, 找到有效的value。
def twoSum(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
hashtable = {}
for i, num in enumerate(nums):
if target - num in hashtable :
return [hashtable[target-num], i]
hashtable[num] = i
return []
2. 4Sum II:
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l)
there are such thatA[i] + B[j] + C[k] + D[l]
is zero.
To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.
Example:
Input: A = [ 1, 2] B = [-2,-1] C = [-1, 2] D = [ 0, 2] Output: 2 Explanation: The two tuples are: 1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
Solution :
def fourSumCount( A, B, C, D):
"""
:type A: List[int]
:type B: List[int]
:type C: List[int]
:type D: List[int]
:rtype: int
"""
hashtable = {}
for a in A:
for b in B :
if a + b in hashtable :
hashtable[a+b] += 1
else :
hashtable[a+b] = 1
count = 0
for c in C :
for d in D :
if -(c + d ) in hashtable :
count += hashtable[-c-d]
return count
这题与上题原理类似,只要设计好hash函数,就能有效解决问题。
3. 4Sum :
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]题目要求找到和为target的不重复的所有四元组,这题除了暴力穷举的O(n^3) ,还想尽可能做得更好,受到同学启发,用hashtable, 让key = nums[i]+nums[j], value = [i, j],这样只需在hashtable中找到两个key值之和为target的数即可了,需要注意的一点是,最后给出答案时应删掉重复的四元组。
Solution :
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
nums.sort()
results = []
hashtable = {}
for i,x in enumerate(nums[:-1]):
for j in xrange(i+1,len(nums)):
y = nums[j]
if x+y in hashtable:
hashtable[x+y].append([i, j])
else :
hashtable[x+y] = [[i, j]]
results = []
for k in hashtable:
if target - k in hashtable :
idxs = [x+y for x in hashtable[k] for y in hashtable[target-k] if len(set(x+y))== 4]
res = [ [nums[y] for y in x ] for x in idxs]
for r in res :
r.sort()
if r not in results :
results.append(r)
return results