Bootstrap

leetcode模板整理

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 = midleft = mid + 1mid = left + (right - left) / 2;一定是配对出现的;(return left找左边界

  • 如果向上取整,right可能会一直和mid相等,导致right值一直不变,进入死循环,所以,right不能赋值为mid;right = mid - 1left = midmid = 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的逻辑处理;
;