1、DFS\BFS遍历树
def dfs(root):
if (root is None):
return
dfs(root.left)
dfs(root.right)
def bfs(root):#相当于层序遍历
queue=[]
queue.append(root);
while (queue):
node = queue.pop(0)#弹出一个节点,然后挨个添加它的左右子树
#pop()默认-1
if (node.left is not None):
queue.append(node.left)
if (node.right is not None):
queue.append(node.right)
#总结
while queue 不空:
cur = queue.pop()
if cur 有效且未被访问过:
进行处理
for 节点 in cur 的所有相邻节点:
if 该节点有效:
queue.push(该节点)
bfs
// 节点访问标识,访问过的节点无需访问(剪枝)
int[][] visited = new int[m][n];
// 队列初始化
Queue<Node> queue = new LinkedList();
// 【第1步】将起点加入队列, 非空进入循环
queue.add(第一个数据)
while(!queue.isEmpty()) {
// 【第2步】 获取当前队列长度即同一层级(辈分)节点个数,并遍历
int size = queue.size(); // 一定要先获取,queue后面要加入下一层级节点
for (int i = 0; i < size; i++) {
// 【第3步】 对同一层级节点逐个寻找下一层有效**路径节点**,找到目标直接返回结果终止搜索。
Node node = queue.poll();
// 下一层节点 比如网格上下左右移动
Node nextNode = node.x + xj;
// 1. 不符合要求的下一层节点直接过滤(比如越界、已经被visited[][]标记访问了)
// 2. 找到目标节点 直接返回结果
// 3. 符合要求的下一层节点放入队列
queue.offer(nextNode)
}
}
// 【第4步】 BFS搜索完成没找到结果,返回-1
return -1;
2、动态规划
#二维矩阵赋初始值
rows, columns = len(grid), len(grid[0])#行 列
dp = [[0 for _ in range(columns)] for _ in range(rows)]
3、回溯(DFS)
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择path.add(当前选择)
backtrack(路径, 选择列表)
撤销选择path.pop()
4、二分查找
//下取整
while(left<right){
int mid=left+(right-left)/2;
if(check(mid)){
left=mid+1;
}else{
right=mid;
}
}
//上取整
while(left<right){
int mid=left+(right-left)/2;
if(check(mid)){
right=mid+1;
}else{
left=mid;
}
}
1、在最后一次循环时:
-
如果向下取整,left可能会一直和mid相等,导致left值一直不变,进入死循环,所以,left不能赋值为mid;
right = mid
和left = mid + 1
和mid = left + (right - left) / 2
;一定是配对出现的;(return left
)找左边界 -
如果向上取整,right可能会一直和mid相等,导致right值一直不变,进入死循环,所以,right不能赋值为mid;
right = mid - 1
和left = mid
和mid = left + (right - left + 1) /2
; 一定是配对出现的。找右边界
2、定义target在左闭右闭的区间,[low, high]
,当 low== high,区间[low, high]依然有效.
int low=0,
high=nums.length-1;
while (low <= high)
定义target在[low, high)
,当low==high,区间[low, high]无意义
int low=0,
high=nums.length;
while (low < high)
5、滚动数组
比如:dp[i]=dp[i-1]+dp[i-2];
要初始化dp[n],每个状态只依赖前两个状态
1、可以以优化为:dp[0],dp[1],dp[2]三个数
for(i=2;i<n;i++){
dp[0]=dp[1];
dp[1]=dp[2];
dp[2]=dp[0]+dp[1];
}
return dp[2];
2、取模
dp[0] = 1;
dp[1] = 1;
for(i=2;i<n;i++){
dp[i%3]=dp[(i-1)%3]+dp[(i-2)%3];
}
return dp[n%3];
二维数组举例,dp[i][j]只依赖于dp[i - 1][j], dp[i][j - 1];
int dp[100][100];
for(int i = 1; i < 100; i++){
for(int j = 0; j < 100; j++){
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
运用滚动数组
int dp[2][100];
for(int i = 1; i < 100; i++){
for(int j = 0; j < 100; j++){
dp[i % 2][j] = dp[(i - 1) % 2][j] + dp[i % 2][j - 1];
}
}
6、树的回溯/递归
搜索一条边的写法:
if (递归函数(root->left)) return ;
if (递归函数(root->right)) return ;
搜索整个树写法:
left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;