Leetcode按类型
字典,哈希表
总结
字典使用和查字典方法
- 遍历列表同时查字典 – 字典查找速度快
- 搜索元素就想字典(hash表)
1
2
3
4
for i, n in enumerate(nums):
if target - n in dct:
return [dct[target - n], i]
dct[n] = i
1
2
nums = [2, 7, 11, 15]
target = 9
1
2
3
4
5
6
7
8
9
10
11
12
13
# 主要思想:
# 判断 if target - n in dct
class Solution:
def twoSum(nums, target):
dct = {}
for i, n in enumerate(nums):
if target - n in dct:
return [dct[target - n], i]
dct[n] = i
result = Solution.twoSum(nums,target)
result
1
2
# 直接从数组中找
# 800ms so slow
1
2
3
4
5
6
7
8
9
10
11
12
13
start = time.time()
class Solution:
def twoSum(nums, target):
for i, n in enumerate(nums):
if (target - n) in nums[i+1:]:
j = nums[i+1:].index(target - n)
return [i, j+i+1]
result = Solution.twoSum(nums,target)
result
end = time.time()
print((start - end))
✅ 169. 多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
1
2
3
4
5
6
7
8
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2
1
2
3
4
5
6
7
8
9
10
# 排序法,自己写的
class Solution:
def majorityElement(self, nums) -> int:
nums.sort()
return nums[(len(nums)-1)//2]
nums = [2,2,1,1,1,2,2]
solution = Solution()
result = solution.majorityElement(nums)
print(result)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Boyer-Moore 投票算法
class Solution:
def majorityElement(self, nums) -> int:
count = 0
candidate = None
for num in nums:
if count == 0:
candidate = num
count += (1 if num == candidate else -1)
return candidate
nums = [2,2,1,1,1,2,2]
solution = Solution()
result = solution.majorityElement(nums)
print(result)
###
🚩1.两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
1
2
3
4
5
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
字典使用和查字典方法
- 遍历列表同时查字典 – 字典查找速度快
- 搜索元素就想字典(hash表)
1
2
3
4
for i, n in enumerate(nums):
if target - n in dct:
return [dct[target - n], i]
dct[n] = i
1
2
nums = [2, 7, 11, 15]
target = 9
1
2
3
4
5
6
7
8
9
10
11
12
13
# 主要思想:
# 判断 if target - n in dct
class Solution:
def twoSum(nums, target):
dct = {}
for i, n in enumerate(nums):
if target - n in dct:
return [dct[target - n], i]
dct[n] = i
result = Solution.twoSum(nums,target)
result
1
2
# 直接从数组中找
# 800ms so slow
1
2
3
4
5
6
7
8
9
10
11
12
13
start = time.time()
class Solution:
def twoSum(nums, target):
for i, n in enumerate(nums):
if (target - n) in nums[i+1:]:
j = nums[i+1:].index(target - n)
return [i, j+i+1]
result = Solution.twoSum(nums,target)
result
end = time.time()
print((start - end))
2️⃣ (1.5h)
✅ 136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
1
2
3
4
5
6
7
8
9
10
11
12
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
2️⃣
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
res = 0
for num in nums:
res ^= num
return res
✅ (40m) 448. 找到所有数组中消失的数字
给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。
找到所有在 [1, n] 范围之间没有出现在数组中的数字。
您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。
1
2
3
4
5
6
7
示例:
输入:
[4,3,2,7,8,2,3,1]
输出:
[5,6]
2️⃣原地修改方法 对i处位置的值为索引将其数字 *-1
1
2
3
4
5
6
7
8
9
class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
for num in nums:
if num < 0:
num = -num
if nums[num-1] > 0:
nums[num-1] *= -1
return [i+1 for i in range(len(nums)) if nums[i] > 0] # 顺序是从前往后的, for, if
✅ (5m) 104. 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
1
2
3
4
5
6
7
8
9
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
2️⃣
✅(30m) 36. 有效的数独
难度中等531收藏分享切换为英文接收动态反馈
请你判断一个 9x9
的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 '.'
表示。
注意:
-
一个有效的数独(部分已被填充)不一定是可解的。
-
只需要根据以上规则,验证已经填入的数字是否有效即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
class Solution: def isValidSudoku(self, board: List[List[str]]) -> bool: for i in range(9): row = set() column = set() gong = set() for j in range(9): if board[i][j] != '.': if board[i][j] in row: return False else: row.add(board[i][j]) if board[j][i] != '.': if board[j][i] in column: return False else: column.add(board[j][i]) if board[i//3*3+j//3][i%3*3+j%3] != '.': if board[i//3*3+j//3][i%3*3+j%3] in gong: return False else: gong.add(board[i//3*3+j//3][i%3*3+j%3]) # print(i) # print(row, column, gong) return True
✅(40m) 49. 字母异位词分组
难度中等760收藏分享切换为英文接收动态反馈
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
1
2
3
4
5
6
7
输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
from collections import defaultdict
res_dict = defaultdict()
for s in strs:
str_key = str(sorted(s))
# print(str_key)
if str_key not in res_dict.keys():
res_dict[str_key] = []
res_dict[str_key].append(s)
# print(res_dict)
return list(res_dict.values())
✅(15m)187. 重复的DNA序列
难度中等169收藏分享切换为英文接收动态反馈
所有 DNA 都由一系列缩写为 'A'
,'C'
,'G'
和 'T'
的核苷酸组成,例如:"ACGAATTCCG"
。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。
编写一个函数来找出所有目标子串,目标子串的长度为 10,且在 DNA 字符串 s
中出现次数超过一次。
示例 1:
1
2
输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC","CCCCCAAAAA"]
示例 2:
1
2
输入:s = "AAAAAAAAAAAAA"
输出:["AAAAAAAAAA"]
1
2
3
4
5
6
7
8
9
10
class Solution:
def findRepeatedDnaSequences(self, s: str) -> List[str]:
res_set = set()
res = []
for i in range(len(s)-9): # 注意,要len-9才能到len-10
if s[i:i+10] in res_set and s[i:i+10] not in res:
res.append(s[i:i+10][:])
else:
res_set.add(s[i:i+10][:])
return res
✅(10m) 202. 快乐数
难度简单621收藏分享切换为英文接收动态反馈
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果 可以变为 1,那么这个数就是快乐数。
如果 n
是快乐数就返回 true
;不是,则返回 false
。
示例 1:
1
2
3
4
5
6
7
输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:
1
2
输入:n = 2
输出:false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution:
def isHappy(self, n: int) -> bool:
def recursion(n):
new_n = 0
while n:
c = n % 10
new_n += c**2
n //= 10
# print(new_n)
if new_n ==1:
return True
elif new_n in n_set:
return False
else:
n_set.add(new_n)
return recursion(new_n)
n_set = set()
return recursion(n)
✅(20m) 205. 同构字符串
难度简单360收藏分享切换为英文接收动态反馈
给定两个字符串 s 和 *t*,判断它们是否是同构的。
如果 s 中的字符可以按某种映射关系替换得到 *t* ,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
示例 1:
1
2
输入:s = "egg", t = "add"
输出:true
示例 2:
1
2
输入:s = "foo", t = "bar"
输出:false
示例 3:
1
2
输入:s = "paper", t = "title"
输出:true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
res_dict = {}
if len(s) != len(t):
return False
for i in range(len(s)):
if s[i] in res_dict:
if t[i] != res_dict[s[i]]:
return False
else:
res_dict[s[i]] = t[i]
s, t = t, s
res_dict = {}
for i in range(len(s)):
if s[i] in res_dict:
if t[i] != res_dict[s[i]]:
return False
else:
res_dict[s[i]] = t[i]
return True
技巧:只要s和t里的字符是一一对应关系即可
1
2
3
4
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
return len(set(s)) == len(set(t)) and len(set(s)) == len(set(zip(s, t)))