八 图与搜索-BFS

127. 拓扑排序

https://www.lintcode.com/zh-cn/problem/topological-sorting/#
这道题分为三步。第一步遍历所有图上的点,生成一个点对应入度的MAP。第二步找到所有入度为0的点,存进队列。第三步,依次把队列里的值放入结果集,随后更新MAP的入度。把相应的邻居入度-1。

public class Solution {
    /*
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
    public ArrayList topSort(ArrayList graph) {
        ArrayList res = new ArrayList<>();
        Map indegree = new HashMap<>();
        for(DirectedGraphNode node : graph) {
            for(DirectedGraphNode nei : node.neighbors){
                indegree.put(nei,indegree.getOrDefault(nei,0)+1);
            }
        }
        Queue q = new LinkedList<>();
        for(DirectedGraphNode node : graph){
            if(indegree.containsKey(node)) continue;
            q.offer(node);
        }
        
        while(!q.isEmpty()){
            DirectedGraphNode cur = q.poll();
            res.add(cur);
            for(DirectedGraphNode nei : cur.neighbors){
                indegree.put(nei,indegree.get(nei)-1);
                if(indegree.get(nei) == 0){
                    q.offer(nei);
                }
            }
        }
        return res;
    }
}
  1. 克隆图
    https://www.lintcode.com/zh-cn/problem/clone-graph/#
    这道题分为三步。
    第一步,用BFS找到图上所有的点(这里是图的遍历BFS需要用一个HASHSET来记录已经遍历过的点)
    第二步,根据所有的点,生成一个旧的点到新的点 映射的MAP
    第三步,根据这个MAP,对所有新的点 构造边。
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        if(node  == null) return null;
        List res = bfs(node);
        
        Map old2New = new HashMap<>();
        for(UndirectedGraphNode cur : res) {
            UndirectedGraphNode newN = new UndirectedGraphNode(cur.label);
            old2New.put(cur,newN);
        }
        
        for(UndirectedGraphNode cur : old2New.keySet()) {
           UndirectedGraphNode newN =  old2New.get(cur);
           for(UndirectedGraphNode nei : cur.neighbors){
               newN.neighbors.add(old2New.get(nei));
           }
        }
        
        return old2New.get(node);
    }
    
    private List bfs(UndirectedGraphNode node){
        Queue q = new LinkedList<>();
        HashSet seen = new HashSet<>();
        q.offer(node);
        seen.add(node);
        while(!q.isEmpty()){
            UndirectedGraphNode cur = q.poll();
            for(UndirectedGraphNode nei : cur.neighbors){
                if(seen.contains(nei)) continue;
                q.offer(nei);

                seen.add(nei);
            }
        }
        return new ArrayList(seen);
    }

第二种,递归写法

Map map = new HashMap<>();
    public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        if(node == null) return null;
        if(map.containsKey(node.label)) return map.get(node.label);
        UndirectedGraphNode copy = new UndirectedGraphNode(node.label);
        map.put(node.label,copy);
        for(UndirectedGraphNode nei : node.neighbors){
            copy.neighbors.add(cloneGraph(nei));
        }
        return copy;
    }

615. 课程表

https://www.lintcode.com/zh-cn/problem/course-schedule/
有向图判定是否有环,用拓扑排序。

public boolean canFinish(int numCourses, int[][] prerequisites) {
        Map ind = new HashMap<>();
        int all = 0;
        Map> chds = new HashMap<>();
        Set seen = new HashSet<>();
        for(int[] pre : prerequisites) {
            if(seen.contains(pre[0]+","+pre[1])) continue;
            seen.add(pre[0]+","+pre[1]);
            ind.put(pre[1],ind.getOrDefault(pre[1],0)+1);
            all++;
            chds.compute(pre[0],(a,b)->{
               if(b == null){
                   Set s = new HashSet<>();
                   s.add(pre[1]);
                   return s;
               }
               b.add(pre[1]);
               return b;
            });
        }
        Queue q = new LinkedList<>();
        for(int i=0; i

605. 序列重构

https://www.lintcode.com/zh-cn/problem/sequence-reconstruction/
拓扑排序的应用,每次只能有一个入度为0的点,这样能构成唯一的拓扑排序,最后再用拓扑排序的序列和ORIGIN序列做匹配。
EDGE CASE:邻接点可能是NULL,还有SEQ 序列可能是空

public boolean sequenceReconstruction(int[] org, int[][] seqs) {
        Map in = new HashMap<>();
        Set s = new HashSet<>();
        Set all = new HashSet<>();
        Map> neis = new HashMap<>();
        for(int[] seq : seqs){
            if(seq.length == 0) continue;
            all.add(seq[0]);
            for(int i=0;i cur = new HashSet<>();
                    cur.add(seq[i+1]);
                    neis.put(seq[i],cur);
                }
                
            }
        }
        //get all 0 degree
        Queue q = new LinkedList<>();
        for(int node : all){
            if(!in.containsKey(node)){
                q.offer(node);
            }
        }
        List top = new ArrayList<>();
        while(!q.isEmpty()){
            int qsize = q.size();
           // System.out.println(qsize);
            if(qsize!=1) return false;
            int cur = q.poll();
            top.add(cur);
            if(neis.get(cur) == null){
                continue;
            } 
            for(int nei : neis.get(cur)){
                in.put(nei,in.get(nei)-1);
                if(in.get(nei) == 0){
                    q.offer(nei);
                }
            }
        }
        if(top.size() != org.length){
            return false;
        } 
        for(int i=0;i

433. 岛屿的个数

https://www.lintcode.com/zh-cn/problem/number-of-islands/
遍历每一个点,一旦发现岛屿,用FLOODFILL去抹除。这个题是BFS的入门题,自己看代码应该可以理解。

public int numIslands(boolean[][] grid) {
        // write your code here
        int count = 0;
        int h = grid.length;
        if(h == 0) return 0;
        int l = grid[0].length;
        for(int i=0; i < h; i++) {
            for(int j=0; j < l; j++) {
                if(grid[i][j]){
                    dfs(grid,i,j);
                    count++;
                }
            }
        }
        return count;
    }
    private void dfs(boolean[][] grid, int y,int x) {
        int h = grid.length;
        int l = grid[0].length;
        grid[y][x] = false;
        if(y>0 && grid[y-1][x]) dfs(grid,y-1,x);
        if(x>0 && grid[y][x-1]) dfs(grid,y,x-1);
        if(y

542. 01 Matrix

https://leetcode.com/problems/01-matrix/description/
首先把0的点加入到队列。其余的点,全部设为最大值。从这些点开始进行BFS。一旦更新了一个点,就把这个更新的点也放进队列。再一次更新。

public int[][] updateMatrix(int[][] matrix) {
        int h = matrix.length;
        int l = matrix[0].length;
        Queue q = new LinkedList<>();
        for(int i = 0;imatrix[cur[0]][cur[1]]+1){
                    matrix[ny][nx]=matrix[cur[0]][cur[1]]+1;
                    q.offer(new int[]{ny,nx});
                }
            }
        }
        return matrix;
    }

解法2,DP

public int[][] updateMatrix(int[][] matrix) {
        int h = matrix.length;
        int l = matrix[0].length;
        for(int i = 0;i=0;i--){
            for(int j=l-1;j>=0;j--){
                if(matrix[i][j] == 0) continue;
                matrix[i][j] = Math.min(matrix[i][j],Math.min(i==h-1?10000:matrix[i+1][j],j==l-1?10000:matrix[i][j+1])+1);
            }
        }
        return matrix;
    }

310. Minimum Height Trees

https://leetcode.com/problems/minimum-height-trees/description/
这道题的思路就是先找到叶子节点,然后抹去,然后再找剩余节点的叶子节点。不断重复。最后只剩下一个或2个就是解。
所以第一步要先根据题目的输入,把GRAPH 构建出来。随后找到所有邻居节点数量为1 的节点。进行更新。然后不断循环。

public List findMinHeightTrees(int n, int[][] edges) {
        
        List res = new ArrayList<>();
        if(n == 1){
            res.add(0);
            return res;
        }
        List> gra = new ArrayList<>();
        for(int i=0;i());
        }
        for(int[] edge : edges){
            gra.get(edge[0]).add(edge[1]);
            gra.get(edge[1]).add(edge[0]);
        }
        for(int i=0;i 2){
            n -= res.size();
            List newRes = new ArrayList<>();
            for(int key : res){
                int tar = gra.get(key).iterator().next();
                gra.get(tar).remove(key);
                if(gra.get(tar).size()==1){
                    newRes.add(tar);
                }
            }
            res = newRes;
            
        }
        return res;
    }

787. Cheapest Flights Within K Stops

https://leetcode.com/problems/cheapest-flights-within-k-stops/description/
首先构造图。
随后开始从起点开始BFS,这里有个剪枝,一旦以走过的路线到了一个之前去过的站点,并且这个走过的路线的票价要贵,那么这个走法就可以抛弃。
K因为是可以停的次数。我用K++,是表示,可以飞几次。
可以停0次=飞1次。

public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        if(src == dst) return 0;
        K++;
        List> gra = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            gra.add(new HashSet<>());
        }
        for (int[] f : flights) {
            gra.get(f[0]).add(new int[]{f[1],f[2]});
        }
        int res = Integer.MAX_VALUE;
        Queue q = new LinkedList<>();
        
        q.offer(new int[]{src,0});
        Map s = new HashMap<>();
        s.put(src,0);
        while(!q.isEmpty() && K>=0){
            int qsize = q.size();
            while(qsize > 0){
                qsize--;
                int[] cur = q.poll();
                if(cur[0] == dst){
                    if(cur[1]

这道题的另外一种解法是DP。dp[i][j] 表示从SRC到I,最多飞J次,要花的最少的钱。
那么转移方程的思考就是 DP I J = MIN(DP I J-1,所有的 flight 里DP【flight[0]】[j-1]+price)

public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        K++;
        int[][] dp = new int[n][K+1];
        for(int i=0;i

做一次优化

public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        K++;
        int[][] dp = new int[n][K+1];
        for(int i=0;i

752. Open the Lock

https://leetcode.com/problems/open-the-lock/description/
这道题的核心就是想到每一个字符的这个节点,通过移一步,可以有8个状态。然后就是BFS常规,找最短路径了。

public int openLock(String[] deadends, String target) {
        String source = "0000";
        Set s = new HashSet<>();
        for(String dead : deadends){
            s.add(dead);
        }
        if(s.contains(source)) return -1;
        
        Set seen = new HashSet<>();
        Queue q = new LinkedList<>();
        q.offer(source);
        seen.add(source);
        int step = 0;
        while(!q.isEmpty()) {
            step++;
            int qsize = q.size();
            while(qsize>0){
                qsize--;
                String cur = q.poll();
                char[] curs = cur.toCharArray();
                for(int i=0;i<4;i++){
                    for(int j=-1;j<=1;j+=2){
                        char tmp = curs[i];
                        curs[i] = (char) ((((curs[i]-'0'+10)+j)%10)+'0');
                        String news = new String(curs);
                        curs[i] = tmp;
                        if(target.equals(news)) return step;
                        if(seen.contains(news) || s.contains(news)) continue;
                        seen.add(news);
                        q.offer(news);
                    }
                }
            }
        }
        return -1;
    }

你可能感兴趣的:(八 图与搜索-BFS)