【算法总结】graph 图的问题
来源:互联网 发布:剑三唱歌捏开脸数据 编辑:程序博客网 时间:2024/05/22 04:06
- 描述及例题:
在一个点线组成的矩阵关系上即为一个图的问题。图的问题主要分为三种类型:
- Deep copy: 在图上建立一个新的图,把原图的关系都copy到新图上。
- Clone Graph
- Copy List with Random Pointer
- Union find: 在图上找到有几个union块。
- Surrounded Regions
- Number of Islands
- Number of Islands II
- Topological sort: 根据pair的关系,或者点线的关系,构建出一个图,找出从start到end的path。
- Alien Dictionary
- Course Schedule
- Course Schedule II
- Word Ladder
- Topological sort
- 解决思路及时间复杂度:
图的问题基本都采用 DFS或者BFS的思路进行解决。- Deep copy:
- 先遍历一遍原图,一边遍历一边建立新的图的点。用hashmap记录原node和新node之间的关系。
- 再复制边的关系。把原图的边的关系,在新的node之间边的关系同样复制
- 以Clone Graph为例,代码如下:
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if(node == null){ return null; } // write your code here ArrayList<UndirectedGraphNode> list = new ArrayList<UndirectedGraphNode>(); HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>(); int size = 0; list.add(node); UndirectedGraphNode newHead = new UndirectedGraphNode(node.label); map.put(node, newHead); while(size<list.size()){ for(UndirectedGraphNode n : list.get(size).neighbors){ if(!map.containsKey(n)){ UndirectedGraphNode newNode = new UndirectedGraphNode(n.label); map.put(n, newNode); list.add(n); } } size++; } //copy edge for(int i=0; i<list.size(); i++){ UndirectedGraphNode newN = map.get(list.get(i)); ArrayList<UndirectedGraphNode> newNeighbor = new ArrayList<UndirectedGraphNode>(); for(UndirectedGraphNode neiNode : list.get(i).neighbors){ newNeighbor.add(map.get(neiNode)); } newN.neighbors = newNeighbor; } return newHead; }
- Union find:
- 遍历整个图,一但找到符合条件的点进行dfs,把整个union进行标记,并记录union个数。
- 以Number of Islands为例:
public class Solution { public int numIslands(boolean[][] grid) { if(grid == null || grid.length == 0 || grid[0].length == 0){ return 0; } int res = 0; boolean[][] visited = new boolean[grid.length][grid[0].length]; for(int i=0; i<grid.length; i++){ for(int j=0; j<grid[0].length; j++){ if(grid[i][j] && !visited[i][j]){ dfs(i, j, grid, visited); res++; } } } return res; } private void dfs(int i, int j, boolean[][] grid, boolean[][] visited){ //end condition if(i>=grid.length || i<0 || j>=grid[0].length || j<0 || visited[i][j] || !grid[i][j]){ return; } visited[i][j] = true; dfs(i+1, j, grid, visited); dfs(i-1, j, grid, visited); dfs(i, j+1, grid, visited); dfs(i, j-1, grid, visited); }}
- Topological sort:
- 先用hashMap记录到所有Node的入度,选择入度为0的点为起点。
- 从起点开始进行bfs,每遍历一个点就入度减一,直到入度为0时,把这个点加入结果顺序中。
- 注意点:环的问题,如果图是有环的,则计数器会产生断层,即某个节点的计数器永远无法清零(有环意味着有的节点被多加了1,然而遍历的时候一次只减一个1,所以导致无法归零),这样该节点也无法加入到结果中。所以我们只要判断这个结果的节点数和实际图中节点数相等,就代表无环,不相等,则代表有环。
- 以Topological sort代码示例:
public class Solution { public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) { ArrayList<DirectedGraphNode> res = new ArrayList<DirectedGraphNode>(); if(graph==null || graph.size()==0){ return res; } //record indegree HashMap<DirectedGraphNode, Integer> map = new HashMap<DirectedGraphNode, Integer>(); for(int i=0; i<graph.size(); i++){ DirectedGraphNode node = graph.get(i); for(DirectedGraphNode n : node.neighbors){ if(map.containsKey(n)){ map.put(n, map.get(n)+1); }else{ map.put(n, 1); } } } //find start point LinkedList<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>(); for(int i=0; i<graph.size(); i++){ if(!map.containsKey(graph.get(i))){ res.add(graph.get(i)); queue.offer(graph.get(i)); } } //travelsal while(!queue.isEmpty()){ DirectedGraphNode node = queue.poll(); for(DirectedGraphNode n : node.neighbors){ if(map.containsKey(n)){ map.put(n, map.get(n)-1); if(map.get(n)==0){ res.add(n); queue.offer(n); } } } } return res; }}
- 代码模板示例:
主要是用dfs或bfs去解决。所以模板以dfs和bfs的递归和迭代两种实现方式为主。- DFS递归:见island那题。注意visited维护。
- DFS迭代:用stack实现。
- BFS递归:一般不用递归实现。
- BFS迭代:用queue实现。
在一个点线组成的矩阵关系上即为一个图的问题。图的问题主要分为三种类型:
- Deep copy: 在图上建立一个新的图,把原图的关系都copy到新图上。
- Clone Graph
- Copy List with Random Pointer
- Clone Graph
- Union find: 在图上找到有几个union块。
- Surrounded Regions
- Number of Islands
- Number of Islands II
- Surrounded Regions
- Topological sort: 根据pair的关系,或者点线的关系,构建出一个图,找出从start到end的path。
- Alien Dictionary
- Course Schedule
- Course Schedule II
- Word Ladder
- Topological sort
- Alien Dictionary
图的问题基本都采用 DFS或者BFS的思路进行解决。
- Deep copy:
- 先遍历一遍原图,一边遍历一边建立新的图的点。用hashmap记录原node和新node之间的关系。
- 再复制边的关系。把原图的边的关系,在新的node之间边的关系同样复制
- 以Clone Graph为例,代码如下:
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if(node == null){ return null; } // write your code here ArrayList<UndirectedGraphNode> list = new ArrayList<UndirectedGraphNode>(); HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>(); int size = 0; list.add(node); UndirectedGraphNode newHead = new UndirectedGraphNode(node.label); map.put(node, newHead); while(size<list.size()){ for(UndirectedGraphNode n : list.get(size).neighbors){ if(!map.containsKey(n)){ UndirectedGraphNode newNode = new UndirectedGraphNode(n.label); map.put(n, newNode); list.add(n); } } size++; } //copy edge for(int i=0; i<list.size(); i++){ UndirectedGraphNode newN = map.get(list.get(i)); ArrayList<UndirectedGraphNode> newNeighbor = new ArrayList<UndirectedGraphNode>(); for(UndirectedGraphNode neiNode : list.get(i).neighbors){ newNeighbor.add(map.get(neiNode)); } newN.neighbors = newNeighbor; } return newHead; }
- Union find:
- 遍历整个图,一但找到符合条件的点进行dfs,把整个union进行标记,并记录union个数。
- 以Number of Islands为例:
public class Solution { public int numIslands(boolean[][] grid) { if(grid == null || grid.length == 0 || grid[0].length == 0){ return 0; } int res = 0; boolean[][] visited = new boolean[grid.length][grid[0].length]; for(int i=0; i<grid.length; i++){ for(int j=0; j<grid[0].length; j++){ if(grid[i][j] && !visited[i][j]){ dfs(i, j, grid, visited); res++; } } } return res; } private void dfs(int i, int j, boolean[][] grid, boolean[][] visited){ //end condition if(i>=grid.length || i<0 || j>=grid[0].length || j<0 || visited[i][j] || !grid[i][j]){ return; } visited[i][j] = true; dfs(i+1, j, grid, visited); dfs(i-1, j, grid, visited); dfs(i, j+1, grid, visited); dfs(i, j-1, grid, visited); }}
- Topological sort:
- 先用hashMap记录到所有Node的入度,选择入度为0的点为起点。
- 从起点开始进行bfs,每遍历一个点就入度减一,直到入度为0时,把这个点加入结果顺序中。
- 注意点:环的问题,如果图是有环的,则计数器会产生断层,即某个节点的计数器永远无法清零(有环意味着有的节点被多加了1,然而遍历的时候一次只减一个1,所以导致无法归零),这样该节点也无法加入到结果中。所以我们只要判断这个结果的节点数和实际图中节点数相等,就代表无环,不相等,则代表有环。
- 以Topological sort代码示例:
public class Solution { public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) { ArrayList<DirectedGraphNode> res = new ArrayList<DirectedGraphNode>(); if(graph==null || graph.size()==0){ return res; } //record indegree HashMap<DirectedGraphNode, Integer> map = new HashMap<DirectedGraphNode, Integer>(); for(int i=0; i<graph.size(); i++){ DirectedGraphNode node = graph.get(i); for(DirectedGraphNode n : node.neighbors){ if(map.containsKey(n)){ map.put(n, map.get(n)+1); }else{ map.put(n, 1); } } } //find start point LinkedList<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>(); for(int i=0; i<graph.size(); i++){ if(!map.containsKey(graph.get(i))){ res.add(graph.get(i)); queue.offer(graph.get(i)); } } //travelsal while(!queue.isEmpty()){ DirectedGraphNode node = queue.poll(); for(DirectedGraphNode n : node.neighbors){ if(map.containsKey(n)){ map.put(n, map.get(n)-1); if(map.get(n)==0){ res.add(n); queue.offer(n); } } } } return res; }}
主要是用dfs或bfs去解决。所以模板以dfs和bfs的递归和迭代两种实现方式为主。
- DFS递归:见island那题。注意visited维护。
- DFS迭代:用stack实现。
- BFS递归:一般不用递归实现。
- BFS迭代:用queue实现。
0 0
- 【算法总结】graph 图的问题
- 面试之图论[Graph],算法摘要总结
- clone Graph的总结之一
- 抠图算法Graph Cut
- POJ 1419 Graph Coloring 图的着色 最大团问题
- Graph Coloring 图着色问题
- Greg and Graph+floyd算法的应用
- 【算法导论-37】Graph的Java实现
- clone Graph的总结之二
- C算法精解---图(Graph)
- Graph Cut(图割算法)
- 4.1 scene graph构建的基本问题
- 关于求解Graph 的Critical Path问题
- Graph(1)--图的基本概念
- poj 1419 Graph Coloring 图着色问题
- KMP算法及相关问题的总结
- 解决算法问题的思路总结
- 遗传算法求解TSP问题的总结
- 学习JavaScript的闭包(closure)
- mongodb分片环境开启认证
- Keil MDK、Sublime的纵向垂直选择
- 安卓HTTP请求之get和post方法。
- IE浏览器安装插件(ocx)提示“windows 已经发现此文件有一个问题”怎么办?
- 【算法总结】graph 图的问题
- OpenCV进行图像相似度对比的几种办法
- 使用照相机拍照后读取当前拍到的图片方法
- HDOJ-1421 搬寝室
- db2cmd建库,备份,恢复等日常操作
- android学习之RelativeLayout
- 美化GridView视图(BaseAdapter)
- 利用Oracle的row_number() over函数消除重 复的记录
- LeetCode 94:Binary Tree Inorder Traversal