KK's blog

每天积累多一些

0%

算法思路:

Leetcode 078的题目。这里作为知识点归纳。

  1. 递归中i=st开始。
  2. 回溯: path递归后去恢复状态。
  3. dfs中传入i+1。
  4. 结果要复制new ArrayList<>(path)
  5. 一般来说,终止条件才加入结果,但由于子集任何path修改都是子集,所有立即加入。

和全排列的区别:

  1. 由于排列可以乱序如[1,2,3]结果是[1,3,2]也就是一个结果需要多次从左向右完全扫描,所以i=0开始且维护visited数组
    组合的结果是按照数组顺序的,所以只要从左到右扫描一次即可,所以用i=st。
  2. 结果方面,排列结果是满长度,而组合不是。所以在加入到res位置上,组合用st来判断是否结束且加入到path就立刻进入最后
    结果,而排列是在终结条件上加入。

注意事项:

  1. 输入不合法,返回[[]]
  2. 记得API是dfs(nums, st, path, result), 4个参数
  3. 递归是i+1,不是start+1

学习要点:

详见DFS要点,大部分DFS题目涉及

  1. 用到全组合的API: dfs(nums, start, path, result), 4个参数
  2. 用到全组合的递归: dfs(nums, i + 1, path, result)
  3. 用到全排列的其他部分包括恢复状态和终止条件(加入res)

应用:

  1. 找所有可能性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def combine(self, nums: List[int]) -> List[List[int]]:
if not nums:
return [[]]
path, result = [], []
self.dfs(nums, 0, path, result)
return result

def dfs(self, nums, st, path, result):
if len(path) == len(nums):
return

for i in range(st, len(nums)):
path.append(nums[i])
result.append(list(path))
self.dfs(nums, i + 1, path, result)
path.pop()

Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public List<List<Integer>> subsets(int[] nums) {
List<Integer> path = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
res.add(new ArrayList<>(path)); //empty set
if(nums == null || nums.length == 0)
return res;
dfs(nums, 0, path, res);
return res;
}

void dfs(int[] nums, int st, List<Integer> path, List<List<Integer>> res) {
if(st == nums.length)
return;

for(int i = st; i < nums.length; i++) {
path.add(nums[i]);
res.add(new ArrayList<>(path));
dfs(nums, i + 1, path, res);
path.remove(path.size() - 1);
}
}

算法分析:

时间复杂度为O(2n) ,空间复杂度O(1)

算法思路:

图用邻接表为输入,思路递归实现, 还要一个机制记录节点访问过没有,可以用HashSet,同时它作为结果存储BFS访问结果。
BFS多用于找最短路径
DFS多用于快速发现底部节点和具体路劲问题(如路径和或打印路径)。

BFS优缺点:
同一层的所有节点都会加入队列,所以耗用大量空间
仅能非递归实现
相比DFS较快,空间换时间
适合广度大的图

DFS优缺点:
无论是系统栈还是用户栈保存的节点数都只是树的深度,所以空间耗用小
有递归和非递归实现
由于有大量栈操作(特别是递归实现时候的系统调用),执行速度较BFS慢
适合深度大的图

如果BFS和DFS都可以用,建议用BFS,因为工业应用中,BFS不用有限的栈空间,可以利用到所有内存。

图DFS

算法步骤:

  1. 不合法情况(已访问、越界、trivial情况等)返回。
  2. 标记为已访问。
  3. 递归访问相邻节点。
  4. DFS路径尽量记录在数组中而非ArrayList中,路径(图)再DFS后要恢复为原状态L332。

Python代码:

1
2
3
4
5
6
7
def dfs(self, graph, start, visited, res):
if start in visited:
return
visited.add(start)
res.append(start)
for node in graph[start]:
self.dfs(graph, visited, node, res)

字符型DFS/组合

跟填位法相同的地方:

  1. 终止条件一样len(path)==TARGET, res.append(list(path)), return
  2. API一样:dfs(nums, start, path, result, visited[optional]), 4个参数
    不同的是,组合模板是的下一轮递归用i + 1, 但这里由于是填位,一位一位加入,所以是start + 1

注意事项:

  1. 输入值为空的情况或空节点
  2. 求得解以后复制path到result中
  3. 终止条件记得return
  4. 每次递归完恢复输入图或中间结果path的状态,递归式用i + 1

Python代码:

1
2
3
4
5
6
7
8
def dfs(self, input, start, TARGET, path, result): 
if len(path) == TARGET:
result.append(list(path))
return
for i in <func>(input[start]):
path.append(i)
self.dfs(input, i + 1, TARGET , path, result)
path.pop()

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# char dfs (type 2 linear) Leetcode 77 Given two integers n and k, return all possible combinations of k numbers out of the range [1, n]
def combine(self, n: int, k: int) -> List[List[int]]:
nums = [i + 1 for i in range(n)]
path, res = [], []
self.dfs2(nums, 0, k, [], res)
return res

def dfs2(self, nums, start, k, path, res):
if len(path) == k:
res.append(list(path))
return
for i in range(start, len(nums)):
path.append(nums[i])
self.dfs2(nums, i + 1, k, path, res)
path.pop()

填位法

跟字符型DFS/组合相同的地方:

  1. 终止条件一样len(path)==TARGET, res.append(list(path)), return
  2. API一样:dfs(nums, start, path, result, visited[optional]), 4个参数
    不同的是,组合模板是的下一轮递归用i + 1, 但这里由于是填位,一位一位加入,所以是start + 1

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
def dfs(self, n, start, path, res, col_set):
if len(path) == TARGET:
res.append(list(path))
return
for i in range(n):
if not self.is_valid(start, i, col_set):
continue
path.append(i)
col_set.add(i)
self.dfs(n, start + 1, path, res, col_set)
col_set.remove(i)
path.pop()

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# filling dfs (type 3) LeetCode 017 Letter Combinations of a Phone Number 
def letterCombinations(self, digits: str) -> List[str]:
if not digits:
return []
path, res = [], []
self.dfs3(digits, 0, path, res)
return res

def dfs3(self, digits, start, path, res):
if len(path) == len(digits): # len(path) == TARGET
res.append("".join(path))
return
keys = DIGIT2CHAR[digits[start]]
for letter in keys:
path.append(letter)
self.dfs3(digits, start + 1, path, res) # remember start + 1
path.pop()

Catalan法(双边递归)

DFS中几乎是最难的类型。考得很少。主要思想是左右儿子递归结果叉乘,再将所有结果返回。所以返回值一定是list

注意事项:

  1. 返回结果是解的集合,所以终止条件返回也需要是一个list
  2. 循环中除掉自己,递归左部分和右半部分,叉乘它们的结果
  3. 与记忆性搜索的模板类似,有时需要和它一起用,见LeetCode 241 Different Ways to Add Parentheses

Python代码:

1
2
3
4
5
6
7
8
9
def dfs(self, input):
if <终止条件>:
return [] # remember to use list
res = []
for i in range(len(input)):
left_res = self.dfs(input[:i])
right_res = self.dfs(input[i + 1:])
res += [<calculate results> for _l in left_res for _r in right_res]
return res

时间复杂度Catalan数为O(C[n] += C[i-1]*C[n-i]),空间复杂度O(1)

记忆性搜索(单边Catalan)

见记忆性搜索

例子:

LeetCode 140 Word Break II
这是单边catalan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
wordSet = set()
for word in wordDict:
wordSet.add(word)
cache = {}
res = self.dfs(s, wordSet, cache)
return [] if len(res) == 1 and not res[0] else res

def dfs(self, s, wordSet, cache):
if not s:
return ['']
if s in cache:
return cache[s]
res = []
for i in range(len(s)):
if s[:i + 1] not in wordSet:
continue
li = self.dfs(s[i + 1:], wordSet, cache)
for ss in li:
res.append((s[:i + 1] + ' ' + ss).strip())

cache[s] = res
return res

例子:

返回结果是解的集合,所以终止条件返回也需要是一个[None]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# catelan dfs (type 4) LeetCode 095 Unique Binary Search Trees II
# return the root of all the possible trees
def generateTrees(self, n: int) -> List[TreeNode]:
nums = [_ + 1 for _ in range(n)]
return self.dfs4(nums, 0, n)

def dfs4(self, nums, start, end): # [start, end)
if start >= end:
return [None] # remember becaues we want the 2 for-loop happen
res = []
for i in range(start, end):
left_root_nodes = self.dfs4(nums, start, i) # 0, 0
right_root_nodes = self.dfs4(nums, i + 1, end) # 1, 1
for left_root_node in left_root_nodes:
for right_root_node in right_root_nodes:
node = TreeNode(nums[i])
node.left = left_root_node
node.right = right_root_node
res.append(node)
return res

应用题型:

LeetCode 095 Unique Binary Search Trees II
LeetCode 241 Different Ways to Add Parentheses

Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* graph: 邻接表
* visited: 记录已访问节点,避免重复访问
* start: DFS的根节点
*/
public void dfs(HashMap<Integer, LinkedList<Integer>> graph, HashSet<Integer> visited, int start){
if(visited.contains(start)){
return;
}
visited.add(start);
System.out.print(start+",");
for(Integer child : graph.get(start)){
dfs(graph, visited, child);
}
}

算法分析:

时间复杂度为O(n),h为树的高度,空间复杂度O(h),如果用系统栈,可理解其为O(1)。

算法思路:

最小堆可以维持堆顶元素为最小值。

应用:

  1. 求数组第k个大的数

Python代码:

1
2
3
4
5
6
7
8
9
10
from heapq import heapreplace, heappush
def min_heap(self, nums: List[int], k: int) -> List[int]:
res = []
for i in range(len(nums)):
if i < k:
heappush(res, nums[i])
elif nums[i] > res[0]:
heapreplace(res, nums[i])

return res

max heap的话,入堆的数转负数,跟堆顶比较的大于号不变,出堆后转为整数
注意第6行res[0]并没有负号,因为res已经是负数

1
2
3
4
5
6
7
8
9
def max_heap(self, nums: List[int], k: int) -> List[int]:
res = []
for i in range(len(nums)):
if i < k:
heappush(res, -nums[i])
elif -nums[i] > res[0]:
heapreplace(res, -nums[i])
res = [-n for n in res]
return res

BFS + Heap

本质是图,求点或点的和或线段路径的最值
这是单源最短路径Dijkstra的典型应用。Dijkstra是每条边的权重(距离), 而不是节点个数最短(BFS模板)。
区别是

  1. 用BFS distance模板。queue变成heap
  2. 遍历时候每个元素多一个weight
  3. visited不再是记录这个节点访问过没有,因为节点可以多次访问,目标是找到这个节点权重最小的路径。visited记录每个节点的最小权重(路径). visited的处理不再是在neighbor的for循环中,而是在循环外,比较权重是否最小,如果不是就跳过。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def bfs(self, graph, start, target) -> List[int]:
    heap, res = ([(weight, start, distance)])), []
    visited = {}
    while heap:
    weight, node, distance = heapq.heappop(heap)
    if node == target and distance <= K:
    return weight
    if node in visited and distance >= visited[node]:
    continue
    visited[node] = distance
    for neighbor, _weight in graph[node]:
    heapq.heappush(heap, (weigth + _weight, neighbor, distance + 1))
    return -1
    BFS的distance模板
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def bfs_layer_v2(self, graph, start, target) -> int:
    queue = deque([(start, 1)])
    visited = {start}
    while queue:
    node, distance = queue.popleft()
    if node == target:
    return distance
    for neighbor in graph[node]:
    if neighbor in visited:
    continue
    queue.append((neighbor, distance + 1))
    visited.add(neighbor)
    return -1

算法分析:

时间复杂度为O(nlogk),空间复杂度O(1)

例子:

LeetCode 787 Cheapest Flights Within K Stops
求只允许停k个站情况下,最便宜机票价格
weight在这里是每条边的价格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:
graph = collections.defaultdict(list)
for pair in flights:
graph[pair[0]].append((pair[1], pair[2]))
heap = ([(0, src, 0)]) # price, node_id, distance
visited = {}
while heap:
p, node, dist = heapq.heappop(heap)
if node == dst and dist <= k + 1:
return p
if node in visited and dist >= visited[node]:
continue
visited[node] = dist
for neighbor, _price in graph[node]:
heapq.heappush(heap, (p + _price, neighbor, dist + 1))
return -1

算法思路:

hasNext, next都涉及计算下一个元素,大部分题目是先计算再返回。只有BST是先返回再计算,因为BST的下一个节点取决于要返回的节点,若返回了,就无法知道下一个节点。

注意事项:

  1. hasNext中,while循环找到下一个符合条件的元素
  2. next中取值后指针要后移

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
def __init__(self):
self.stack = []
<add to stack>

def next(self) -> int:
if self.hasNext():
return self.stack.pop()
return None

def hasNext(self) -> bool:
while <until find the next element>:
<calculate>
return <next element>

例子:

LeetCode 341 Flatten Nested List Iterator
实现Nested List的Iterator。Nested List是NestedInteger的数组,NestedInteger可以是int,也可以是Nested List
nestedList = [NestedInteger]
NestedInteger 用isInteger()来判断
-> 2 by getInteger()
-> [2, 3] by getList()

1 记得在next和hasnext去pop不是stack[-1]

  1. Iterator题目都是用Stack,比如BST Iterator
  2. init和next都可以假设是用int来完成,用reversed加入
  3. next则要考虑两种情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class NestedIterator(TestCases):

def __init__(self, nestedList):
self.stack = []
for i in reversed(range(len(nestedList))):
self.stack.append(nestedList[i])

def next(self) -> int:
if self.hasNext():
return self.stack.pop().getInteger()
return None

def hasNext(self) -> bool:
while self.stack and not self.stack[-1].isInteger():
nestedList = self.stack.pop().getList()
for i in reversed(range(len(nestedList))):
self.stack.append(nestedList[i])
return True if self.stack else False

应用题型:

LeetCode 251 Flatten 2D Vector
LeetCode 281 Zigzag Iterator
LeetCode 341 Flatten Nested List Iterator
LeetCode 173 Binary Search Tree Iterator

算法分析:

next操作时间复杂度为O(N + V)/NO(1),N为所有数,V为复合结构数

常用知识点

类型 函数名 作用 输入参数 返回值 例子
for range 和len结合使用相当于取某范围List下标,第三个参数为步长 N/A N/A for i in range(len(nums))前闭后开,用逗号
for in 枚举列表的每个数 N/A N/A for n in nums
for range 逆序遍历 N/A N/A for i in range(len(nums) - 1, -1, -1)前闭后开, 或用reversed(range(len(nums)))
for enumerate 枚举List的下标和数值,与range不同的是它不能指定范围和步长 N/A N/A for i, n in enumerate(nums)
Math max/min 取最大值 Num Num max_len = max(2, 3) 或min(1, 2, 3)
Math pow 求幂值 Num Num val = pow(2, 3)
Math int str转int或将float变成int String Num val = int(‘123’), val = int(2.6) -> 2
Math math.ceil/floor 求向上或下取整 Num Num import math, val = math.ceil(5/2), math.floor(5/2)
Math float(‘inf’) 无穷大值 N/A Num val = float(‘inf’) or float(‘-inf’)
Math min 求数组中的正数的最小值 N/A Num min(n for n in nums if n > 0)
Math len 求数组中的正数的个数 N/A Num len([n for n in nums if n > 0])
Math sum 求数组和 N/A Num sum(nums)
Math abs 求绝对值 Num Num abs(-1)
Math //与int 求整数值 Num Num //是比它小的整数如-2.8就是-3,只在负数是有区别。写程序用的更多是int(num / a)结果是-2,这和Java一致
String str 任意类型变成字符串 Any String str(2)
String replace 替换 String String ‘abc’.replace(‘c’, ‘d’)
String format 格式化字符串 Any String f”{a} of {b}” 或者 ‘{} of {}’.format(a, b)
String [] 得到某一个字符 N/A Char s[2]
String [] 得到子串(前闭后开) N/A string s = ‘abc’, s[:2] -> ‘ab’, s[2:] -> ‘c’
String len 得到字符串长度 N/A int num = len(s)
String [::-1] 反转字符串 N/A String new_str = s[::-1]
String [:-1] (DFS中)去掉最后一个字符 N/A String path = path[:-1]
String N/A 两个字符串叉乘 N/A List a_list = [s + c for s in s1 for c in s2]
String > 比较两个字符串 N/A boolean ‘111’ > ‘21’ -> False, ‘21’ == ‘21’ -> True
String index/find 查找返回下标 str str ‘word’.index(‘w’, 2).从下标2开始找. ‘word’.find(‘w’) 若找不到返回-1.
String upper 变成全部大写 str str ‘word’.upper()
String lower 变成全部大写 str str ‘WORD’.lower()
String startswith 是否以某个字母开头 str Boolean ‘word’.startswith(‘w’)
String endswith 是否以某个字母结尾 str Boolean ‘word’.endswith(‘d’)
String strip, lstrip, rstrip 去掉空格 N/A str ‘word ‘.strip(), ‘word ‘.lstrip(), ‘word ‘.rstrip()
String split 用分隔符变成List str List ‘a,b’.split(‘,’)
String + 一个个字符加到字符串末 N/A N/A res += ‘g’
String in 查看某个字符是否属于一个字符集合里 N/A bool if char in ‘([{‘ 可以避免用list
String isalpha 是否字母 N/A bool ‘ab’.isalpha()
String isdigit 是否数字 N/A bool ‘23’.isdigit()
String ascii_lowercase a-z的所有字母 str str import string
string.ascii_lowercase
String ord 一个字母的ASCII str str ord(‘A’) = 65
String eval 计算字符串的数值,变量,函数运算结果,返回数字 str Num eval(‘5+ 6’) = 11, num = 1, eval(num + 1) = 2, eval(‘f(2)’)
String ljust 靠左右边补空格 str str line.ljust(maxWidth), line.ljust(maxWidth, ‘#’)
List [] 初始化列表 N/A N/A li = [],这是空列表,不能通过索引取值
List [] 初始化固定大小的列表 N/A N/A li = [0] * 10, [None] * 10 -> 创建一个list, * 是复制只能用于标量,若矢量是复制ref如[[]] * 10, 要用[[] for _ in range(10)]
List len 大小 N/A int num = len(li)
List append 尾部加入 Any N/A li.append(‘apple’)
List insert 头部加入 Any N/A li.insert(0, ‘apple’)
List pop 头部/某位置删除 Any N/A li.pop(0), li.pop(2)
List remove 按值删除 Any N/A li.remove(3)
List + 两个list合并 N/A N/A list1 + list2
List extend 两个list合并到第一个 Any N/A li.extend([‘apple’, ‘banana’])
List join 加入分隔符 List String ‘,’.join(li), 将字符列表变成字符串’’.join(char_list)
List sort 原地排序,如果List的元素是tuple,按第一个元素排序 List N/A li.sort(), 如果不改变原数组用list(li)先复制
List sort 按字符串长度降序排列 List N/A words.sort(key=len, reverse=True), intervals.sort(key=lambda x: x[0]), 按两个key来排序li.sort(key=lambda x: (x[0], x[1]))先顺序再逆序li.sort(key=lambda x: (x[0], -x[1]))
List sorted 非原地排序 List N/A nums[idx+1:] = sorted(nums[idx+1:])
List list 复制list List List new_list = list(old_list)
List list 扩展一倍一样的list List List new_list = nums * 2
List [] 反转list List List new_list = li[::-1]跟反转string一样,反转子列表nums[idx+1:] = nums[len(nums)-1:idx:-1]
List [-1] 返回list中最后一个元素 T int li[-1],而不是dp[len(li)-1]广泛用于DP题
List index list中找某个元素 T int li.index(2), 找不到的话抛出异常,先要检查if 9 in li2 else -1. 字符串用find
List count list中计算某个元素值的个数 T int li.count(‘a’)
List [:] 批量替换成list中某些元素 N/A N/A nums[start:end + 1] = res
List [::-1] reverse sublist N/A N/A nums[:k] = nums[:k][::-1]先取sublist再倒转
deque deque 初始化队列 N/A N/A from collections import deque
queue = deque()
queue = deque([node])
deque append 入列 T N/A queue.append(node)
deque popleft 出列 Num T s = queue.popleft()
deque appendleft 队首入列 Num T s = queue.appendleft()较少用
deque [0] 看列首元素 N/A T queue = [], s = queue[0]
List(Heap) heapify 对list最小堆排序 List N/A from heapq import heapify, pq = [2, 3], heapify(pq) 若最大堆,则将所有值取负加入堆
List(Heap) heappush 入堆 List, T N/A from heapq import heappush
heappush(pq, 4)
List(Heap) heappop 出堆 List T from heapq import heappop
heappop(pq)
List(Heap) heapreplace 置换堆 T N/A heapq.heapreplace(pq, 4)= heappush(pq, 4) + heappop(pq)
List(Heap) [0] 看堆顶元素 N/A T pq[0]
List(Stack) append 入栈 T N/A stack = [], stack.append(node)
List(Stack) pop 出栈 N/A T stack = [], s = stack.pop()
List(Stack) [] 看栈顶元素 N/A T stack = [], s = stack[-1]
Dictionary {} 初始化字典 N/A N/A di = {}, di = {1: ‘a’, 2: ‘b’}
Dictionary {} 初始化字典带初始key N/A N/A di = collections.defaultdict(int), defaultdict(list)避免第一次赋值时需要写if语句,一定用。只有用下标di[2]才会产生key和value,其他2 in di, di.keys()都不会产生key. collections.defaultdict(lambda: [0, 0])用于value是pair, 默认返回1: collections.defaultdict(lambda: 1)
Dictionary [] 获得字典的值 T T di[key]
Dictionary [] 插入到字典 T T di[key] = 2
Dictionary items Dict的所有pairs N/A K,V for k, v in di.items()
Dictionary items Dict的所有keys N/A List for k in di.keys(), 类型不是List,若要,则list(di.keys())
Dictionary in 是否含有某个key N/A boolean if key in di
Dictionary pop 删除某个key N/A N/A di.pop(key)
Set {} 产生一个Set N/A Set b = set(), b = set([‘a’, ‘b’])
Set add set增加一个元素 T N/A b.add(‘c’)
Set remove set删除一个元素 T N/A b.remove(‘c’)
Set set List转换成Set或反之 N/A N/A s = set(l), l = list(s)
bisect bisect 二分法查找下标插入位置 Num Num 跟greater_position一样, from bisect import bisect, bisect([], 3) -> 0, bisect([2], 3) -> 1, bisect([3], 3) -> 1, bisect([4], 3) -> 0。还可以用于统计小于等于target的个数,如bisect([0, 1], 1) -> 2
bisect bisect_left 二分法查找下标插入位置 Num Num 似于greater_or_equal_position但若equal时,取第一个,但greater_or_equal_position是取最后一个. 用于LIS
bisect insort 二分法查找下标插入位置且插入 Num Num 似于greater_position,插入复杂度为O(n)
bisect bisect 二分法查找二维数组 Num Num bisect.bisect([[0, 1], [0, 2], [1, 2], [1, 3]], [1]) -> [1, 2]下标,若找[1, 2] -> [1, 3]下标
Lambda func/expr…for…in 整型数组变字符串数组 List List [str(x) for x in list]
Others nonlocal N/A N/A N/A nonlocal i. 用于内部函数内的变量,类似于全局变量,不需要作为参数传入到内部函数且可以修改不用返回。见key value store
Others @dataclass N/A N/A N/A 省略__init__,__eq__等函数。
from dataclasses import dataclass
@dataclass
class Product:
  name: str
Others return 返回tuple值 N/A N/A return a, b 不要括号
Others isinstance 判断输入是什么类型 N/A bool isinstance(stack[2], list)
Others Counter 计算List和字符串频率 List dict from collections import Counter
di = Counter(nums)
di = Counter(‘apple’)
graph = Counter(c for word in words for c in word)
Counter({c: [] for word in words for c in word})
Others [] 初始化NxM矩阵为0 N/A N/A a = [[1] * M] * N不能复制矢量。[[0 for _ in range(M)] for _ in range(N)] 先col再row
Others randint 求[start, end]之间随机值 Num Num import random
random.randint(0, 1) -> 0/1
Others map, max 求矩阵最大值 [][] T max(map(max, matrix))
Others or 若0返回1 N/A N/A a or 1 -> a if a != 0, 1 if a == 0
Others or 若None返回空数组 N/A N/A for child in root.children or []
OrderedDict OrderedDict 类似于LinkedHashMap,dict的key的插入顺序排序 N/A N/A di = collections.OrderedDict()
di[‘a’] = 2
re search search只match一次 str str re.search(r’(\+|\-)?\d+’, ‘-23.1e2’).group() -> -23
re sub 全部用regex替代类似Java中的replaceAll str str re.sub(r’\s+’, ‘’, ‘a 6 7’) -> a67
Exception Exception 抛出异常 N/A N/A raise Exception(‘abc’)

总结:
除了deque, Stack, List的实现都是List
插入append, insert
删除pop, popleft(deque)

初始化列表:
创建一个list: li = [0] * 10, [False] * 10 而不是[False * 10], [0 * 10]这是乘法
创建一个list of list不用乘号: [[0 for _ in range(M)] for _ in range(N)], [[] for _ in range(10)]

if left_val可能为整数或None,要写成if left_val is not None,否则若left_val = 0, 会False
i += 1没有i++
if 0 < i < len(nums) 不像Java一样,Python可以连续比较范围
所有int都是long
22//5 = 4
22/5 = 4.4

def myFunc(e):
return e[‘year’]
cars.sort(reverse=True, key=myFunc)

由于Python的数字类型都是Numeric(自动识别为Integer, Float, Complex Numbers),所以自动变成小数,不像Java是int
数据类型

True/False
and/or/not
pass什么都不做 if a: pass

&, ^异或, ~取反(~3), |, <<, >>

lo = hi = 0
swap: a, b = b, a
elif
return -res if is_negative else res
if root / if not root
if not nums 包含(None以及len(nums) == 0
Node(0)没有new
zip是将两个list的元素同步合成tuple,以短的为终结点。例如[i + j for i, j in zip(li, li2)] -> [5, 7], li = [1, 2], li2 = [4, 5, 6]
函数中更改输入list如f(list) -> list = [‘’],不会改变原list,必须更改任意元素: list[:] = [‘’]
匿名函数和重载: ListNode.__lt__ = lambda x, y: (x.val < y.val)
Python中自定义obj可以任意定义属性,所以若要给某属性赋值如node.value,一定要match类定义里边的,不是node.val = 5。

补集:
list(set(li) - set(li2))
[n for n in self.all if n not in set(li)]
并集:
list(set(li) | set(li2))
list(set(li + li2))
交集:
list(set(li) & set(li2))
[n for n in li if n in set(li2)]

10的6次方,不能用10^6,这是异或,用1e6或pow(10, 6)
self.maxDepth

用_i来表示内部使用,dict_表示与关键字不重复

三个引号就是多行comment,#是一行comment
换行用 \

Python基础
Python命名规则
Python下划线

Free mock interview