提示:本篇共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
哈希表篇到这里就结束了,若文章中有表述不当的地方还望大家多多指出,字符串篇
见吧。