LeetCode---Depth-first && Breadth-first

417. Pacific Atlantic Water Flow
思路:构造两个二维数组分别存储大西洋和太平洋的结果,先初始化边界,然后从边界出发,深度优先遍历,标记满足条件的所有节点

static int[] dx = new int[]{-1,0,0,1};
static int[] dy = new int[]{0,1,-1,0}; 
public List<int[]> pacificAtlantic(int[][] matrix) {
    List<int[]> res = new ArrayList<int[]>();
    if(matrix == null || matrix.length == 0) return res;
    int m = matrix.length;
    int n = matrix[0].length;
    boolean[][] p = new boolean[m][n];
    boolean[][] a = new boolean[m][n];
    
    //初始化两条边
    for(int j = 0; j < n; j++){
        p[0][j] = true;
        a[m - 1][j] = true;
    }
    
    for(int i = 0; i < m; i++){
        p[i][0] = true;
        a[i][n - 1] = true;
    }
    
    //判断该点能不能流入两个海
    for(int j = 0; j < n; j++){
        dfs(matrix,p,0,j);
        dfs(matrix,a,m - 1,j);
    }
    
    for(int i = 0; i < m; i++){
        dfs(matrix,p,i,0);
        dfs(matrix,a,i,n - 1);
    }
    
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            if(p[i][j] && a[i][j]){
                res.add(new int[]{i,j});
            }
        }
    }
    return res;
}

public void dfs(int[][] matrix,boolean[][] dp,int row,int col){
    dp[row][col] = true;
    int m = matrix.length;
    int n = matrix[0].length;
    for(int i = 0; i < 4; i++){
        int p = row + dx[i];
        int q = col + dy[i];
        if(p < m && p >= 0 && q < n && q >= 0){
            if(matrix[row][col] <= matrix[p][q] && dp[p][q] == false) dfs(matrix,dp,p,q);
        }
    }
}
473. Matchsticks to Square
思路:首先和不是4的整数倍,return false,然后将数组逆序排序,这样能更快的搜索到结果,然后深度优先遍历最后能将数组遍历完并且每条边都能等于target即可

public boolean makesquare(int[] nums) {
    if(nums == null || nums.length < 4) return false;
    int sum = 0;
    for(int num : nums){
        sum += num;
    }
    if(sum % 4 != 0) return false;
    //将数组逆序排序以后能更快的搜索到结果
    Arrays.sort(nums);
    reverse(nums);
    return dfs(nums,new int[4],0,sum / 4);
}

public boolean dfs(int[] nums,int[] sum,int idx,int target){
    if(idx == nums.length && sum[0] == target && sum[1] == target && sum[2] == target){
        return true;
    }
    
    for(int i = 0; i < 4; i++){
        if(sum[i] + nums[idx] > target) continue;
        sum[i] += nums[idx];
        if(dfs(nums,sum,idx + 1,target)) return true;
        sum[i] -= nums[idx];
    }
    return false;
}

public void reverse(int[] nums){
    int i = 0;
    int j = nums.length - 1;
    while(i < j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
        i++;
        j--;
    }
}
总结
207. Course Schedule:利用拓扑排序,不断取出入度为0的节点,判断最终计数器的值和节点个数是否一致,等价于判断有没有环
133. Clone Graph:利用map存下node.label和node对,方便查找
训练
332. Reconstruct Itinerary:利用map将节点和与之关联的节点保存起来,并利用优先队列进行排序,最后输出结果的时候,优先将堵塞的路径节点添加到结果前面
210. Course Schedule II:思路同207,但是要考虑没有先决条件的情况
200. Number of Islands:深度优先遍历,依次将每个岛中的1都变为0,同时计数
472. Concatenated Words:首先根据字符串长度排序,将短的一依次存入dict用作备选,之后动态规划依次判断后面的长字符串能否用短字符串拼接起来
329. Longest Increasing Path in a Matrix:深度优先遍历,依次找到递增的序列,注意利用之前的结果避免重复搜索
279. Perfect Squares:动态规划,res[n] = Min{ res[n - i * i] + 1 },  n - i * i >= 0 && i >= 1
310. Minimum Height Trees:首先将图的结构用map保存下来,然后取出叶子节点,依次将叶子节点和分支去除,得到新的叶子节点,若最后剩下的节点数<=2则作为结果返回
提示
1、将结果从后往前添加的经验-->332题
2、在二维数组中深度优先遍历的经验 构造两个数组保存四个方向-->417 200 329题
3、拓扑排序的算法-->207 210题
原文地址:https://www.cnblogs.com/LeonNew/p/6288993.html