目录
参考文献:https://leetcode-cn.com/leetbook/read/hash-table/xh7j6v/
一、哈希集 - 用法
// C++ implementation
#include <unordered_set> // 0. include the library
int main() {
// 1. initialize a hash set
unordered_set<int> hashset;
// 2. insert a new key
hashset.insert(3);
hashset.insert(2);
hashset.insert(1);
// 3. delete a key
hashset.erase(2);
// 4. check if the key is in the hash set
if (hashset.count(2) <= 0) {
cout << "Key 2 is not in the hash set." << endl;
}
// 5. get the size of the hash set
cout << "The size of hash set is: " << hashset.size() << endl;
// 6. iterate the hash set
for (auto it = hashset.begin(); it != hashset.end(); ++it) {
cout << (*it) << " ";
}
cout << "are in the hash set." << endl;
// 7. clear the hash set
hashset.clear();
// 8. check if the hash set is empty
if (hashset.empty()) {
cout << "hash set is empty now!" << endl;
}
}
# Python implementation
# 1. initialize the hash set
hashset = set()
# 2. add a new key
hashset.add(3)
hashset.add(2)
hashset.add(1)
# 3. remove a key
hashset.remove(2)
# 4. check if the key is in the hash set
if (2 not in hashset):
print("Key 2 is not in the hash set.")
# 5. get the size of the hash set
print("Size of hashset is:", len(hashset))
# 6. iterate the hash set
for x in hashset:
print(x, end=" ")
print("are in the hash set.")
# 7. clear the hash set
hashset.clear()
print("Size of hashset:", len(hashset))
参考文献:https://leetcode-cn.com/leetbook/read/hash-table/xhge27/
二、使用哈希集查重
/*
* Template for using hash set to find duplicates by C++.
*/
bool findDuplicates(vector<Type>& keys) {
// Replace Type with actual type of your key
unordered_set<Type> hashset;
// 范围 for 循环
for (Type key : keys) {
if (hashset.count(key) > 0) {
return true;
}
hashset.insert(key);
}
return false;
}
参考文献:https://leetcode-cn.com/leetbook/read/hash-table/xhzxa5/
三、存在重复元素
3.1 题目要求
3.2 解决过程
个人实现
法一:哈希集合 - set 实现。空间复杂度 O(n),时间复杂度 O(n)。
2020/08/23 - 85.06% (44ms)
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
hashset = set()
for i in range(len(nums)):
if nums[i] in hashset:
return True
hashset.add(nums[i])
return False
法二:哈希映射 - dict 实现。空间复杂度 O(n),时间复杂度 O(n)。
2020/08/23 - 48.28% (52ms)
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
hashmap = dict()
for i in range(len(nums)):
if hashmap.get(nums[i]) == 1: # dict.get() 比 dict[i] 更好
return True
hashmap[nums[i]] = 1
return False
法三:哈希映射 - collections.Counter 实现。关于 Counter 类详见 链接。
2020/08/23 - 69.11% (48ms)
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
if len(nums) < 2:
return False
counter = collections.Counter(nums)
if counter.most_common(1)[0][1] > 1:
return True
return False
法四:数组排序 + 滑动窗口。空间复杂度 O(n),时间复杂度 O(nlogn)。
2020/08/23 - 69.11% (48ms)
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
if len(nums) < 2:
return False
sorted_nums = sorted(nums) # 数组排序, 如果 nums.sort() 空间复杂度就是 O(1)
for i in range(len(nums)-1):
if sorted_nums[i] == sorted_nums[i+1]:
return True
return False
官方实现与说明
// Java implementation
public boolean containsDuplicate(int[] nums) {
for (int i = 0; i < nums.length; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[j] == nums[i]) return true;
}
}
return false;
}
// Time Limit Exceeded
// Java implementation
public boolean containsDuplicate(int[] nums) {
Arrays.sort(nums);
for (int i = 0; i < nums.length - 1; ++i) {
if (nums[i] == nums[i + 1]) return true;
}
return false;
}
// Java implementation
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<>(nums.length);
for (int x: nums) {
if (set.contains(x)) return true;
set.add(x);
}
return false;
}
参考文献
https://leetcode-cn.com/leetbook/read/hash-table/xhzjp6/
https://leetcode-cn.com/problems/contains-duplicate/solution/cun-zai-zhong-fu-yuan-su-by-leetcode/
四、只出现一次的数字
4.1 题目要求
4.2 解决过程
个人实现
法一:哈希集合 - set 实现。遍历数组,将出现过一次的元素加入哈希集合,将出现过两次的元素移除哈希集合,那么最后剩下的元素即为只出现一次的数字。空间复杂度 O(n),时间复杂度 O(n)。
2020/08/23 - 97.83% (36ms) -
class Solution:
def singleNumber(self, nums: List[int]) -> int:
hashset = set() # 哈希集合 (如果用两个哈希集合最后作差就会比较麻烦)
for i in range(len(nums)):
if nums[i] not in hashset:
hashset.add(nums[i]) # 添加出现过 1 次的元素
else:
hashset.remove(nums[i]) # 移除出现过 2 次的元素 # set.discard() 也行
return hashset.pop() # 剩下唯一元素即为目标元素
法二:哈希映射 - Counter 实现。
2020/08/23 - 61.54% (48ms)
class Solution:
def singleNumber(self, nums: List[int]) -> int:
counter = collections.Counter(nums)
return counter.most_common()[-1][0]
法三:数组排序 + 滑动窗口。空间复杂度 O(n),时间复杂度 O(nlogn)。
2020/08/23 - 92.35% (40ms)
class Solution:
def singleNumber(self, nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
sorted_nums = sorted(nums) # 数组排序, 如果 nums.sort() 空间复杂度就是 O(1)
for i in range(0, len(nums)-1, 2):
if sorted_nums[i] != sorted_nums[i+1]:
return sorted_nums[i]
return sorted_nums[-1]
法四:位运算 - 异或 XOR。利用异或运算相同为 0 相异为 1 的性质,遍历整个数组依次异或,最终即可得到唯一元素。从而满足题目要求的 空间复杂度 O(1),时间复杂度 O(n)。
2020/08/23 - 92.35% (40ms) - 最佳
class Solution:
def singleNumber(self, nums: List[int]) -> int:
num = nums[0]
for i in range(1, len(nums)):
num = num ^ nums[i]
return num
官方实现与说明
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return reduce(lambda x, y: x ^ y, nums)
参考文献
https://leetcode-cn.com/leetbook/read/hash-table/xhsyr2/
五、两个数组的交集
5.1 题目要求
5.2 解决过程
个人实现
法一:交集运算。强制类型转换后,执行交集运算。似乎一时想不出更简单的方法了。
2020/08/23 - 95.63% (52ms)
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return set(nums1) & set(nums2) # return set(nums1).intersection(set(nums2))
法二:哈希集合。空间复杂度 O(min(m, n)),时间复杂度 O(m+n)。
2020/11/02 - 99.50% (44ms) - 最佳
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
hashset = set()
for i in nums1:
hashset.add(i)
result = []
for j in nums2:
if j in hashset:
result.append(j)
hashset.remove(j)
return result
官方实现与说明
class Solution:
def set_intersection(self, set1, set2):
return [x for x in set1 if x in set2]
def intersection(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
set1 = set(nums1)
set2 = set(nums2)
if len(set1) < len(set2):
return self.set_intersection(set1, set2)
else:
return self.set_intersection(set2, set1)
2020/08/23 - 74.68% (60ms)
class Solution:
def intersection(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
set1 = set(nums1)
set2 = set(nums2)
return list(set2 & set1)
参考文献
https://leetcode-cn.com/leetbook/read/hash-table/xh4sec/
六、快乐数
6.1 题目要求
6.2 解决过程
官方实现与说明
class Solution:
def isHappy(self, n: int) -> bool:
def get_next(n):
total_sum = 0
while n > 0:
n, digit = divmod(n, 10)
total_sum += digit ** 2
return total_sum
seen = set()
while n != 1 and n not in seen:
seen.add(n)
n = get_next(n)
return n == 1
2020/08/24 - 91.55% (40ms)
class Solution:
def isHappy(self, n: int) -> bool:
def get_next(number):
total_sum = 0
while number > 0:
number, digit = divmod(number, 10)
total_sum += digit ** 2
return total_sum
slow_runner = n
fast_runner = get_next(n)
while fast_runner != 1 and slow_runner != fast_runner:
slow_runner = get_next(slow_runner)
fast_runner = get_next(get_next(fast_runner))
return fast_runner == 1
2020/08/24 - 91.55% (40ms)
class Solution:
def isHappy(self, n: int) -> bool:
cycle_members = {4, 16, 37, 58, 89, 145, 42, 20}
def get_next(number):
total_sum = 0
while number > 0:
number, digit = divmod(number, 10)
total_sum += digit ** 2
return total_sum
while n != 1 and n not in cycle_members:
n = get_next(n)
return n == 1
2020/08/24 - 97.47% (36ms) - 最佳
参考文献
https://leetcode-cn.com/leetbook/read/hash-table/xh1k9i/
https://leetcode-cn.com/problems/happy-number/solution/kuai-le-shu-by-leetcode-solution/