测试用例的选取
List item
返回a和b的最大公约数
math.gcd(a,b)
Python的计数器
cnt = Collections.counter(str)
双端队列
【构造】queue = collections.deque()
【方法】左端弹出:queue.popleft()
【方法】右端弹出:queue.pop()
【方法】左端加入:queue.appendleft()
【方法】右端弹出:queue.append()
lambda函数
a = lambda x,y,z:(x+y)*y-z
要点:
(1)lambda 函数不能包含命令,
(2)包含的表达式不能超过一个。
说明:一定非要使用lambda函数;任何能够使用它们的地方,都可以定义一个单独的普通函数来进行替换。我将它们用在需要封装特殊的、非重用代码上,避免令我的代码充斥着大量单行函数。
lambda匿名函数的格式:冒号前是参数,可以有多个,用逗号隔开,冒号右边的为表达式。其实lambda返回值是一个函数的地址,也就是函数对象。
例: intervals.sort(key=lambda x:x[0])
可以进行对多维数组按某一行或某一列排序
set()函数用来构造无重复的元素合集
a = set()
增删元素操作: a.remove(), a.add()
正负无限规避最大(小)值判断,float(‘inf’), float(’-inf’)
- 类型
- 例题
- 核心思想
BFS核心就在于按层遍历,也就是所有能分步按层去解决的问题都适用这种搜索方法。以下列举一些BFS的特点:
1.一定是用到deque的结构来模拟队列
2.队列有一个初始节点
3.内层循环,每次处理从队列中出队一个元素
4.对元素进行扩张(新入列)
5.对于扩张后满足条件的点再进行处理
6.外层循环,继续循环处理deque中的元素,直到deque为空,则代表所有点都已经完成了扩张。
(完成扩张的点也进行标记)
- 具体技巧及代码模板
对于无向图搜索来说,必须得标志是否访问过,如果要求在原图(矩阵)中进行计算,一个技巧是将访问过的节点设为负值。(或者灵活地先将所有未访问的值设为-1,访问后设为正值)
首先,BFS使用队列,把每个还没有搜索到的点依次放入队列,然后再弹出队列头部元素当做当前的遍历点。
(1)不需要确定当前遍历到了哪一层
while queue not None:
cur = queue.pop()
for 节点 in cur 的所有相邻节点:
if 该节点有效且未被访问过:
queue.push(当前节点)
(2)需要确定当前遍历到了哪一层,增加参数level表示当前遍历的层数,size 表示当前遍历层有多少元素(或者说当前层源点的个数,用来构造遍历循环)。
queue = collections.deque()
level = 0
while queue not None:
size = queue.size()
while (size -= 1 ):
for 节点 in cur 的所有相邻节点:
if 该节点有效且未被访问过:
queue.push(当前节点)
#queue.append((nx,ny))用来记录下一层将要被访问的邻节点
levle += 1
- 类型
- 例题
- 核心思想
遍历整个网络,当遇到符合条件的点时,从该点开始进行深度优先搜索,将dfs搜索过的点置-1或0。继续搜索网络下一个符合条件的点直至网络中所有的点。
- 具体技巧及代码模板
def dfs(self, grid, cur_i, cur_j):
if cur_i < 0 or cur_j < 0 or cur_i == len(grid) or cur_j == len(grid[0]) or grid[cur_i][cur_j]!=1:
return 0
area = 1
grid[cur_i][cur_j] = 0
for di, dj in [[1,0], [-1,0], [0,1], [0,-1]]:
next_i, next_j = cur_i + di, cur_j + dj
area = self.dfs(grid, next_i, next_j)+area
return area
主循环
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
ans = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
ans = max(ans, self.dfs(grid, i, j))
return ans
- 例题
- 核心思想
暴力法遍历时时间复杂度会过高。则使用滑动窗口(类似于双指针)思想。以LC3题为例,定义“”不重复子串” 的起始和结束位置分别为start 和 end, 随着找到符合条件的子串出现,或者当前子串不再符合条件,则将start的值增加(指针向右移动),重复该项操作直至再次符合(不符合)题目条件。
- 代码模板
以题LC209为例,去找到长度最小的子数组
min_len = n
cur_len = 0
cur_sum = 0
left = 0 #指向子数组的第一个元素
#主循环的i相当于右指针,指向了查询子数组的最后一个元素
for i in range(len(n)):
cur_len += 1
cur_sum += nums[i]
#一旦出现了满足条件的子数组,就迭代一次最小子数组长度,同时left指针向右移动一个直至不符合条件的数组产生。
while cur_sum >= s:
min_len = min(cur_len, min_len)
cur_sum -= nums[left]
cur_len -= 1
left += 1
边界条件,考虑如果数组所有数相加都不能达到值s时的情况,
if cur_len == 0 and cur_sum < s:
return 0
- 例题
- 核心思想
能够应用前缀和思想的题目一般为求解一个连续或不连续的子数组
- 代码模板
以题LC560为例,
num_times = collections.defaultdict(int) #存储某“前缀和”出现的次数,这里用collections.defaultdict来定义它
num_times[0] = 1 #用来记录出现前缀和为0的次数为1
cur_sum = 0 #用来记录当前前缀和
res = 0
for i in range(len(nums)):
cur_sum += nums[i]
if cur_sum - k in num_times:
res += num_times[cur_sum-k]
num_times[cur_sum] += 1
return res