提示:本篇共8道力扣题目供大家食用,时间自行把控~
1、本篇是算法刷题系列文章的第 3 篇,写此系列的目的是为了让自己对题目的理解更加深刻。
2、本系列博客主要参考了卡哥的 代码随想录博客 以及 卡哥本人B站讲解的视频 代码随想录B站视频 ,强烈推荐给大家,因为本人学习中 Python为主,因此博客主要由 Python 代码呈现给大家,需要其他语言的版本,卡哥博客链接自取。
Python 中,字典是一系列 键值对 。每个键都与一个值相关联,你可以使用键来访问与之相关联的值。与键相关的值可以是数字、字符串、列表乃至字典。键值对 对是两个相关联的值。指定键时,Python将返回与之相关联的值。键和值之间用冒号分隔,键值对之间用逗号分割。如下所示:favorite_languages= {
'jen': 'Python',
'sarah': 'C++',
'jake': 'Go',
'jane': 'Java',
}
print(favorite_languages['jake'])
# 输出:
Go
Tom 最喜欢的语言是 Html 。favorite_languages['Tom'] = 'Html'
print(favorite_languages)
# 输出
{'jen': 'Python',
'sarah': 'C++',
'jake': 'Go',
'jane': 'Java',
'Tom': 'Html'}
= 赋予新值即可。如:将字典favorite_languages 中添加 Tom 最喜欢的语言改为是 R 。favorite_languages['Tom'] = 'R'
print(favorite_languages['Tom'])
# 输出
R
del语句 将相应的键值对彻底删除。使用时,必须指定字典名和要删除的键,删除 Tom 的例子如下所示。del favorite_languages['Tom']
print(avorite_languages)
# 输出
{
'jen': 'Python',
'sarah': 'C++',
'jake': 'Go',
'jane': 'Java',
}
# 遍历键值对
for name, language in favorite_languages.items():
print(name+"'s favorite language is " + language)
# 输出:
jen's favorite language is Python
sarah's favorite language is C++
jake's favorite language is Go
jane's favorite language is Java
# 遍历所有键
for name in favorite_languages.keys():
print(name)
# 输出:
jen
sarah
jake
jane
# 遍历所有值
for language in favorite_languages.values():
print(language)
# 输出:
Python
C++
Go
Java
Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指 Hash table 就可以了)。简单理解就是字典。 一般哈希表都是用来快速判断一个元素是否出现集合里。两个物品A和B 都映射到了 索引下标 1 的位置,这一现象叫做 哈希碰撞。一般哈希碰撞有两种解决方法, 拉链法和线性探测法。
- 拉链法: 在发生冲突的
索引1的位置后面联接一个链表,然后把发生冲突的元素都被存储在链表中。这样我们就可以通过索引找到物品A和B了。注意:拉链法就是要选择适当的哈希表的大小。- 线性探测法: 使用线性探测法,一定要保证
tableSize(哈希表大小)大于dataSize(数据规模)。 例如:冲突的位置,放了物品A,那么就向下找一个空位放置物品B的信息。
s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。注意: 若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。法1排序法: 根据题意可知,只有字符串
s和t长度相同时,才有可能是字母异位词。因此将字符串s和t进行排序,然后对比字符串s和t是否相同就可以解决本题。
法2哈希法: 借助数组,因为a~z的ASCII码是连续的,因此可以a可以映射为数组下标0的位置,z可以映射为数组下标25的位置。因此,我们可以先统计字符串s中每个字母出现的频次,然后在遍历字符串t将出现的字母频次拿刚刚创建的数组做减法。若最后数组是全零数组,就证明字符串s和t是有效的字母异位词,否者则不是,代码见下方。
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
len_s = len(s)
len_t = len(t)
if len_s != len_t:
return False
else:
s = sorted(s)
t = sorted(t)
for i in range(len_s):
if s[i] == t[i]:
continue
else:
return False
return True
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
hashTable = [0] * 26
# 1、创建数组,记录s中的字母频次
for i in s:
hashTable[ord(i) - ord("a")] += 1
# 2、做减法
for i in t:
hashTable[ord(i) - ord("a")] -= 1
# 3、检查数组中的数据, hashTable数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
for i in range(26):
if hashTable[i] != 0:
return False
return True
nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。set 对两个数组进行去重,然后遍历较短的数组并与另一数组中的数字进行比较,若相同则添加到 ans 数组中,遍历结束返回 ans 数组即可,下面给出参考代码,可简化。class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1 = list(set(nums1))
nums2 = list(set(nums2))
len_1 = len(nums1)
len_2 = len(nums2)
ans = []
if len_1 > len_2:
for i in range(len_2):
if nums2[i] not in nums1:
continue
else:
ans.append(nums2[i])
else:
for i in range(len_1):
if nums1[i] not in nums2:
continue
else:
ans.append(nums1[i])
return ans
n 是不是快乐数。快乐数的定义如下:「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和;
- 然后重复这个过程直到这个数变为
1,也可能是无限循环但始终变不到1;- 如果这个过程
结果为 1,那么这个数就是快乐数;- 如果
n是 快乐数 就返回true;不是,则返回false。
sum,建立record = set() 记录过程中产生的存 sum值,若 record 中有重复的元素,则返回 False ,否则继续计算,直到为 1 返回 True 。class Solution:
def getSum(self, n):
sum_ = 0
# 从个位上依次进行取值,求和
while n:
sum_ += (n % 10) * (n % 10)
n //= 10
return sum_
def isHappy(self, n: int) -> bool:
# 记录中间结果
record = set()
while True:
n = self.getSum(n)
if n == 1:
return True
# 如果中间结果重复出现,说明陷入死循环了,该数不是快乐数
if n in record:
return False
else:
record.add(n)
nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。时间复杂度 O(nlogn),空间复杂度O(n)。nums=[2,3,3,4,5],target=6 在 pop 出第一个 3 之后其实 nums 被更新了,后面的 3 的位置其实往前走了一位,那么它在 原nums 中的位置就应该是现在位置 +1 呀。参考链接class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 双指针
left = 0
right = len(nums) - 1
temp = nums.copy()
temp.sort()
while left < right:
sum_ = temp[left] + temp[right]
if sum_ > target:
right -= 1
elif sum_ < target:
left += 1
else:
break
# 返回原数组的下标
p=nums.index(temp[left])
nums.pop(p)
k=nums.index(temp[right])
if k>=p:
k=k+1
return [p,k]
target-num[index] 的值存在哈希表中。在遍历数组的时候,只需要向hashtable 去查询是否有和目前遍历元素比配的数值,如果有,就找到了匹配对,如果没有,就把目前遍历的元素放进hashtable 中,因为hashtable 存放的就是我们访问过的元素。class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 哈希法
hashtable = dict()
for index, value in enumerate(nums):
if target - value in hashtable:
return [hashtable[target-value], index]
else:
hashtable[value] = index
return []
nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:0 <= i, j, k, l < n ;nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 。1、首先定义一个
字典哈希,key放a和b两数之和,value放a和b两数之和出现的次数。
2、遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到哈希表中。
3、定义变量count,用来统计a+b+c+d = 0出现的次数。
4、再遍历大C和大D数组,找到如果0-(c+d)在哈希表中出现过的话,就用count把哈希表中key对应的value也就是出现次数统计出来。
5、最后返回统计值count就可以了
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
hashmap = dict()
# 统计 a、b 两个数组中的元素和,以及次数
for n1 in nums1:
for n2 in nums2:
if n1 + n2 in hashmap:
hashmap[n1+n2] += 1
else:
hashmap[n1+n2] = 1
# 找到如果 `0-(c+d)` 在哈希表中出现过的话,就用 `count` 把哈希表中 `key` 对应的 `value`也就是出现次数统计出来。
count = 0
for n3 in nums3:
for n4 in nums4:
key = 0 - (n3+n4)
if key in hashmap:
count += hashmap[key]
return count
ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次。26的数组 去记录 magazine 里字母出现的次数。然后再用 ransomNote去验证这个数组是否包含了 ransomNote 所需要的所有字母即可。class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
hashtable = [0] * 26
for x in magazine:
hashtable[ord(x) - ord('a')] += 1
for x in ransomNote:
if hashtable[ord(x) - ord('a')] == 0:
return False
else:
hashtable[ord(x) - ord('a')] -= 1
return True
nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。i,代表三数中的第1个数,left = i + 1,代表第2个数,right = len(nums) - 1,代表第3个数 。注意:遍历数组前要将原始数组进行排序。 sum_ = nums[i] + nums[left] + nums[right],代表三数之和,通过判断 sum_ 与 0 的关系从而将满足题意的结果放入结果集 result 中。关于去重的相关逻辑,建议大家观看 代码随想录:三数之和去重逻辑 。class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
# 存放结果集
result = []
for i in range(len(nums)):
if nums[i] > 0:
break
# 去重
if i > 0 and nums[i] == nums[i-1]:
continue
left = i + 1
right = len(nums) - 1
while left < right:
sum_ = nums[i] + nums[left] + nums[right]
if sum_ > 0:
right -= 1
elif sum_ < 0:
left += 1
else:
result.append([nums[i], nums[left], nums[right]])
# 去重,
while left != right and nums[right] == nums[right - 1]:
right -= 1
while left != right and nums[left] == nums[left + 1]:
left += 1
left += 1
right -= 1
return result
给你一个由
n个整数组成的数组nums,和一个目标值target。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]](若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n;a、b、c和d互不相同;nums[a] + nums[b] + nums[c] + nums[d] == target;- 你可以按 任意顺序 返回答案 。
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
n = len(nums)
res = []
for i in range(n):
if i > 0 and nums[i] == nums[i - 1]: continue # 对nums[i]去重
for k in range(i+1, n):
if k > i + 1 and nums[k] == nums[k-1]: continue # 对nums[k]去重
p = k + 1
q = n - 1
while p < q:
if nums[i] + nums[k] + nums[p] + nums[q] > target: q -= 1
elif nums[i] + nums[k] + nums[p] + nums[q] < target: p += 1
else:
res.append([nums[i], nums[k], nums[p], nums[q]])
# 对nums[p]和nums[q]去重
while p < q and nums[p] == nums[p + 1]: p += 1
while p < q and nums[q] == nums[q - 1]: q -= 1
p += 1
q -= 1
return res
哈希表篇到这里就结束了,若文章中有表述不当的地方还望大家多多指出,字符串篇见吧。