哈希表是一种数据结构,它使用哈希函数将键映射到存储桶或槽位中。它通过将键转换为索引来实现快速的插入、查找和删除操作。哈希表通常用于需要高效查找的场景,如字典、缓存和数据库中。
常见哈希结构
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法!
看这篇博文应该就能对哈希表有个基础的了解了。来吧!一文彻底搞定哈希表!_哈希表庆哥_庆哥Java的博客-CSDN博客
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
(1)暴力枚举法
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
left = 0
right = 0
for i in range(len(nums)):
for j in range(left+1,len(nums)):
if nums[j] + nums[left] == target:
return [left,j]
else:
j = j + 1
left = left + 1
时间很长,没想到这也能打败10%。
(2)哈希表
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
hash_table = dict()
for i, num in enumerate(nums):
if target - num in hash_table:
return [hash_table[target-num], i]
else:
hash_table[num] = i
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
示例 3:
输入: strs = ["a"]
输出: [["a"]]
心得:该题主要是找到具有相同字母的异构单词之间的共性,提取出来作为哈希表的键,值就是具有相同字母的异构单词列表。没做出来,想到了用数字代替字母排序,但是只想到了加法,觉得不具有唯一性就没用。看了讨论区,大佬用质数的方法代替字母,这样质数的乘积是唯一的,相同字母组成的异构单词就具有相同的性质,就可以用字典来储存表示了。官方答案写的没看懂。
class Solution(object):
def groupAnagrams(self, strs):
"""
:type strs: List[str]
:rtype: List[List[str]]
"""
map = {
'a':2,'b':3,'c':5,'d':7,'e':11,'f':13,'g':17,'h':19,'i':23,'j':29,'k':31,'l':37,'m':41,
'n':43,'o':47,'p':53,'q':59,'r':61,'s':67,'t':71,'u':73,'v':79,'w':83,'x':89,'y':97,'z':101
}
resmap={}
reslist = []
for str in strs:
m = 1
for i in range(len(str)):
m*=map[str[i]]
if not m in resmap:
resmap[m]=[]
resmap[m].append(str)
# print(resmap.values())
return [j for j in resmap.values()]
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1] 输出:9
心得:哈希表实在掌握的太差,只能用最蠢的方法暴力解出来,但是时间已经超出限制了。
class Solution(object):
def longestConsecutive(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums)==0:
return 0
if len(nums)==1:
return 1
i = 0
j = 0
cur_len = 1
max_len = 1
for i in range(len(nums) - 1):
for j in range(len(nums) - 1 - i):
if nums[j] > nums[j+1]:
temp = nums[j+1]
nums[j+1] = nums[j]
nums[j] = temp
for k in range(len(nums) - 1):
if nums[k+1]==nums[k]:
continue
elif nums[k+1]==nums[k] + 1:
cur_len = cur_len + 1
if max_len < cur_len:
max_len = cur_len
else:
cur_len = 1
return max_len
return nums
看了一眼解析,发现使用的set(),只能说掌握的知识太少了,去看了set()的用法后自己终于写出来了一版。但是时间和内存的消耗还是很大。
class Solution(object):
def longestConsecutive(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
up = 1
down = 1
cur_len = 1
max_len = 1
if len(nums)==0:
return 0
if len(nums)==1:
return 1
hash_table = set()
for i in range(len(nums)):
hash_table.add(nums[i])
j = 0
while j < len(nums)-1:
hash_table.discard(nums[j])
if nums[j] + up in hash_table:
hash_table.remove(nums[j] + up)
up = up + 1
elif nums[j] - down in hash_table:
hash_table.remove(nums[j] - down)
down = down + 1
else:
cur_len = up + down - 1
up = 1
down = 1
if cur_len > max_len:
max_len = cur_len
j = j + 1
return max_len
发现可以hash_table=set(nums),内存减少了一些,竟然击败增加了这么多。
看了官方的答案写出来的一版。更加的简洁。
class Solution(object):
def longestConsecutive(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
cur_len = 1
max_len = 1
if len(nums)==0:
return 0
if len(nums)==1:
return 1
hash_table = set(nums)
for num in hash_table:
if num - 1 not in hash_table:
# 如果表中没有比它小1的,就开始寻找大1的,然后一直往上找
cur_num = num
cur_len = 1
# 如果比它大1存在,则开始计数
while cur_num + 1 in hash_table:
cur_num = cur_num + 1
cur_len = cur_len + 1
if max_len < cur_len:
max_len = cur_len
# 如果有比它小1的,直接不管,继续循环,直到找到没有比它小1的
return max_len
做完哈希表的题发现有几个重点,一个是什么时候用,在需要快速查找一个元素是否在集合里时,就要用到哈希表。一个是需要掌握数组,dict(),set()的基础用法,不然真的很麻烦。
1、Python的数组分三种类型:
(1) list 普通的链表,初始化后可以通过特定方法动态增加元素。
定义方式:arr = [元素]
文章python数组使用(超级全面)_27Up的博客-CSDN博客
(2) Tuple 固定的数组,一旦定义后,其元素个数是不能再改变的。
定义方式:arr = (元素)
Tuple 没有的方法:
[1] 不能向 tuple 增加元素,没有 append 、 extend 、insert 等方法。
[2] 不能从 tuple 删除元素,没有 remove 或 pop 方法。
[3] 不能在 tuple 中查找元素,没有 index 方法(index是查找而不是索引,索引直接用下标即可,如:t[0])。
Tuple 可以转换成 list, 反之亦然。
转换方式为:t = list( t ),反之:arr = tuple( arr )
(3) Dictionary 词典类型, 即是Hash数组。
定义方式:arr = {元素k:v}
#Dictionary 的用法比较简单,它可以存储任意值,并允许是不同类型的值,下面实例来说明:
#下面例子中 a 是整数, b 是字符串, c 是数组,这个例子充分说明哈希数组的适用性。
dict_arr = {'a': 100, 'b':'boy', 'c':['o', 'p', 'q']}
#可以直接增加一个元素,如果同名,则会改变原来的key的元素的值
dict_arr['d'] = 'dog'
#输出所有的key
print dict_arr.keys()
#输出所有的value
print dict_arr.values()
文章Python 集合set详解(超详细)_python set集合_LeoATLiang的博客-CSDN博客
remove() 方法用于移除集合中的指定元素。该方法不同于 discard() 方法,因为 remove() 方法在移除一个不存在的元素时会发生错误,而 discard() 方法不会。
clear() 方法用于移除集合中的所有元素。
删除则使用del函数。