您的位置:首页 > 其它

LintCode图论&搜索题总结

2016-06-19 16:20 267 查看
LintCode上Graph & Search那一章有这些题目:





15. Permutations

给定一连串数字,要求它的所有可能的排列。

比如123的全排列为[123, 132, 213, 231, 312, 321]

这道题用DFS搜索,递归搜索树如下所示:



画出递归搜索树之后,代码自然就不难了。

每次加入list数组中的元素不能在之前出现过。

public ArrayList<ArrayList<Integer>> permute(ArrayList<Integer> nums) {
ArrayList<ArrayList<Integer> > res = new ArrayList();
if (nums == null || nums.size() == 0) {
return res;
}
ArrayList<Integer> list = new ArrayList<Integer>();
helper(res, list, nums);
return res;
}

private void helper(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> list, ArrayList<Integer> nums) {
if (list.size() == nums.size()) {
res.add(new ArrayList<Integer>(list));
return;
}

for (int i = 0; i < nums.size(); i++) {
if (list.contains(nums.get(i))) {
continue;
}
list.add(nums.get(i));
helper(res, list, nums);
list.remove(list.size() - 1);
}
}
时间复杂度是O(n! * n)

16. Permutations II

这道题和上一道题有点类似,但是输入的数组会有重复的数字,比如[122]的全排列是[122, 212, 221]



这就要求我们在处理重复的元素上花一些功夫了。所以我们需要先对数组进行排序,然后只能连续地选,这样就可以避免生成重复的solution。

需要加一个visit数组,表示哪些已经访问过了。如果当前下标已经访问过了,则不要把它加进了。如果有2个连续的元素相等,并且前一个元素没有访问过,那么后面一个元素也不要加进去。

public ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums) {
ArrayList<ArrayList<Integer> > res = new ArrayList();
if (nums == null || nums.size() == 0) {
return res;
}
Collections.sort(nums);
boolean[] visit = new boolean[nums.size()];
ArrayList<Integer> list = new ArrayList<Integer>();
helper(res, list, nums, visit);
return res;
}

private void helper(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> list, ArrayList<Integer> nums, boolean[] visit) {
if (list.size() == nums.size()) {
res.add(new ArrayList<Integer>(list));
return;
}

for (int i = 0; i < nums.size(); i++) {
if (visit[i] || (i != 0 && nums.get(i) == nums.get(i-1) && visit[i-1])) {
continue;
}
visit[i] = true;
list.add(nums.get(i));
helper(res, list, nums, visit);
list.remove(list.size() - 1);
visit[i] = false;
}
}


String Permutation I

跟Permutations那道题基本一样,只不过这次处理的是字符串,不是数字数组了。

需要注意的是,如果是求长度:

A) 对于String str来说,调用的是str.length()

B) 对于ArrayList<Integer> list来说,调用的是list.size()

C) 对于char[] arr来说,调用的是arr.length

如果是求是否包含某个元素:

A) 对于String str来说,调用的是str.indexOf(char c)

B) 对于ArrayList<Integer> list来说,调用的是list.contains(int a)

private void dfs(List<String> res, char[] s, String path) {
if (path.length() == s.length) {
res.add(new String(path));
return;
}

for (int i = 0; i < s.length; i++) {
if (path.indexOf(s[i]) != -1) {
continue;
}
path += s[i];
dfs(res, s, path);
path = path.substring(0, path.length() - 1);
}
}
public List<String> stringPermutation2(String str) {
List<String> res = new ArrayList<String>();
char[] s = str.toCharArray();
Arrays.sort(s);
dfs(res, s, "");
return res;
}


10. String Permutation II

跟上道题类似,不过输入多了重复的字符,比如abb。处理方法和Permutation II那道题是一样的,加入visit数组判断.

private void dfs(List<String> res, char[] s, String path, boolean[] visit) {
if (path.length() == s.length) {
res.add(new String(path));
return;
}

for (int i = 0; i < s.length; i++) {
if (visit[i] == true || (i != 0 && s[i] == s[i-1] && !visit[i-1])) {
continue;
}
visit[i] = true;
path += s[i];
dfs(res, s, path, visit);
path = path.substring(0, path.length() - 1);
visit[i] = false;
}
}
public List<String> stringPermutation2(String str) {
List<String> res = new ArrayList<String>();
char[] s = str.toCharArray();
Arrays.sort(s);
boolean[] visit = new boolean[str.length()];
dfs(res, s, "", visit);
return res;
}


17. Subsets

给定一个含不同整数的集合,返回其所有的子集。子集中的元素排列必须是非降序的,解集必须不包含重复的子集。

这个跟permutation相比,就不用等到list的容量达到指定值才加进去了。每次DFS都能加元素



public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
ArrayList<ArrayList<Integer>> res = new ArrayList();
ArrayList<Integer> list = new ArrayList<Integer>();
Arrays.sort(nums);
helper(res, list, nums, 0);
return res;
}

private void helper(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> list, int[] nums, int pos) {
res.add(new ArrayList<Integer>(list));
for (int i = pos; i < nums.length; i++) {
list.add(nums[i]);
helper(res, list, nums, i + 1);
list.remove(list.size() - 1);
}
}


18. Subsets II

跟上一道题类似,只不过输入的数中会有重复的元素。注意要跳过重复元素



public ArrayList<ArrayList<Integer>> subsetsWithDup(ArrayList<Integer> S) {
ArrayList<ArrayList<Integer>> res = new ArrayList();
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.sort(S);
helper(res, list, S, 0);
return res;
}

private void helper(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> list, ArrayList<Integer> num, int pos) {
res.add(new ArrayList<Integer>(list));
for (int i = pos; i < num.size(); i++) {
if (i != pos && num.get(i) == num.get(i-1)) {
continue;
}
list.add(num.get(i));
helper(res, list, num, i + 1);
list.remove(list.size() - 1);
}
}


以上四道题都是典型的DFS深度搜索递归。他们的模板可以背下来。可以借助画图来帮助理解。

33. N-Queens



N皇后问题,输入一个数字n,要求出n*n方格下所有符合N皇后规则的棋盘格局。N皇后不能出现在同一直线上(横、竖、对角线)。

这种要求出所有方案类型的题目,典型的是用深搜DFS,并且这道题可以套DFS的模板。

一层一层的向下扫描,需要用到一个pos数组,其中pos[i]表示第i行皇后的位置,然后从第0开始递归,每一行都一次遍历各列,判断如果在该位置放置皇后会不会有冲突,以此类推,当到最后一行的皇后放好后,一种解法就生成了,将其存入结果res中,然后再还会继续完成搜索所有的情况。

private ArrayList<String> draw(ArrayList<Integer> pos) {
ArrayList<String> res = new ArrayList();
int n = pos.size();
for (int i = 0; i < n; i++) {
String tmp = new String();
for (int j = 0; j < n; j++) {
if (j == pos.get(i)) {
tmp += "Q";
continue;
}
tmp += ".";
}
res.add(tmp);
}
return res;
}
private boolean isValid(ArrayList<Integer> pos, int col) {
int row = pos.size();
for (int i = 0; i < row; i++) {
// same column
if (col == pos.get(i)) {
return false;
}
// diagonal
if (Math.abs(i - row) == Math.abs(pos.get(i) - col)) {
return false;
}
}
return true;
}

private void dfs(ArrayList<Integer> pos, ArrayList<ArrayList<String>> res, int n) {
if (pos.size() == n) {
ArrayList<String> tmp = draw(pos);
res.add(tmp);
return;
}

for (int i = 0; i < n; i++) {
if (isValid(pos, i)) {
pos.add(i);
dfs(pos, res, n);
pos.remove(pos.size() - 1);
}
}

}

ArrayList<ArrayList<String>> solveNQueens(int n) {
ArrayList<ArrayList<String>> res = new ArrayList();
if (n <= 0) {
return res;
}
dfs(new ArrayList<Integer>(), res, n);
return res;
}


34. N-Queens II
跟上道题很类似,只不过只要求出N皇后的个数,而不是列举出总方案数。记得要声明一个static全局静态变量来记录个数。

private static int res;
private boolean isValid(ArrayList<Integer> pos, int col) {
int row = pos.size();
for (int i = 0; i < row; i++) {
// same column
if (col == pos.get(i)) {
return false;
}
// diagonal
if (Math.abs(i - row) == Math.abs(pos.get(i) - col)) {
return false;
}
}
return true;
}

private void dfs(ArrayList<Integer> pos, int n) {
if (pos.size() == n) {
res++;
return;
}
for (int i = 0; i < n; i++) {
if (isValid(pos, i)) {
pos.add(i);
dfs(pos, n);
pos.remove(pos.size() - 1);
}
}
}

public int totalNQueens(int n) {
// res = 0;
dfs(new ArrayList<Integer>(), n);
return res;
}


136. Palindrome Partitioning

对字符串进行划分,求出所有使得它能成为回文串的划分组合。

Given s =
"aab"
, return:
[
["aa","b"],
["a","a","b"]
]

这种题也是经典的DFS深搜题,可以直接套用DFS模板。
private boolean isPalindrome(String s) {
int left = 0, right = s.length() - 1;
while (left < right) {
if (s.charAt(left) != s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
private void dfs(List<List<String>>res, ArrayList<String> path, String s, int pos) {
if (pos == s.length()) {
res.add(new ArrayList<String>(path));
return;
}
for (int i = pos; i < s.length(); i++) {
String prefix = s.substring(pos, i + 1);
if (isPalindrome(prefix)) {
path.add(prefix);
dfs(res, path, s, i + 1);
path.remove(path.size() - 1);
}
}
}
public List<List<String>> partition(String s) {
List<List<String>> res = new ArrayList();
if (s == null) {
return res;
}
dfs(res, new ArrayList<String>(), s, 0);
return res;
}


135. Combination Sum

给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T。C中的数字可以无限制重复被选取。

例如,给出候选数组[2,3,6,7]和目标数字7,所求的解为:

[7],

[2,2,3]
由于是从set集合里找元素来进行组合,集合的特点就是每个元素是唯一的。这也是一道可以直接套用DFS模板的题目:
private void dfs(List<List<Integer>> res, ArrayList<Integer> path, int target, int[] candidates, int pos) {
if (target == 0) {
res.add(new ArrayList<Integer>(path));
return;
}
for (int i = pos; i < candidates.length; i++) {
if (candidates[i] > target) {
break;
}
path.add(candidates[i]);
dfs(res, path, target - candidates[i], candidates, i);
path.remove(path.size() - 1);
}

}
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList();
if (candidates == null) {
return res;
}
Arrays.sort(candidates);
dfs(res, new ArrayList<Integer>(), target, candidates, 0);
return res;
}


153. Combination Sum II

跟上道题不同的是,这次是从一群有重复的数字的集合里找组合,同一个数字会在集合里出现多次。

但是每个数字只允许取一次。需要注意的是对重复数字的处理,出现重复数字就跳过那一次循环。

private void dfs(List<List<Integer>> res, ArrayList<Integer> path, int target, int[] num, int pos) {
if (target == 0) {
res.add(new ArrayList<Integer>(path));
return;
}
for (int i = pos; i < num.length; i++) {
if (num[i] > target) {
break;
}
if (i != pos && num[i] == num[i-1]) {
continue;
}
path.add(num[i]);
dfs(res, path, target - num[i], num, i + 1);
path.remove(path.size() - 1);
}
}
public List<List<Integer>> combinationSum2(int[] num, int target) {
List<List<Integer>> res = new ArrayList();
if (num == null) {
return res;
}
Arrays.sort(num);
dfs(res, new ArrayList<Integer>(), target, num, 0);
return res;
}


90. k Sum II

解题思路: 由于k Sum是求个数,所以考虑动态规划,直接DFS会超时。而k Sum II 是求所有具体的解,所以直接DFS.

思路跟 subsets 类似,可以想象成求一些特殊的subsets,加入result时,要符合subset的和等于target

本题与 Combination Sum II 也非常类似

private void dfs(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> path, int[] A, int k, int target, int pos) {
if (path.size() == k) {
if (target == 0) {
res.add(new ArrayList<Integer>(path));
}
return;
}
for (int i = pos; i < A.length; i++) {
path.add(A[i]);
dfs(res, path, A, k, target - A[i], i + 1);
path.remove(path.size() - 1);
}
}
public ArrayList<ArrayList<Integer>> kSumII(int[] A, int k, int target) {
ArrayList<ArrayList<Integer>> res = new ArrayList();
if (k <= 0) {
return res;
}
dfs(res, new ArrayList<Integer>(), A, k, target, 0);
return res;
}


137. Clone Graph

给一个邻接表表示的图,返回一个它的深拷贝。这道题的关键在于用BFS首先克隆所有的点,然后再克隆所有的边。克隆点的时候需要用到HashSet来保存每一个节点。

/**
* Definition for undirected graph.
* class UndirectedGraphNode {
*     int label;
*     ArrayList<UndirectedGraphNode> neighbors;
*     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
* };
*/
public class Solution {
/**
* @param node: A undirected graph node
* @return: A undirected graph node
*/
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return null;
}

// 1. use bfs to get all nodes
HashSet<UndirectedGraphNode> set = new HashSet<UndirectedGraphNode>();
Queue<UndirectedGraphNode> q = new LinkedList<UndirectedGraphNode>();
set.add(node);
q.offer(node);
while (!q.isEmpty()) {
UndirectedGraphNode root = q.poll();
for (UndirectedGraphNode n : root.neighbors) {
if (!set.contains(n)) {
set.add(n);
q.offer(n);
}
}
}
ArrayList<UndirectedGraphNode> nodes = new ArrayList<UndirectedGraphNode>(set);

// 2. clone all nodes
HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
for (UndirectedGraphNode tmp : nodes) {
map.put(tmp, new UndirectedGraphNode(tmp.label));
}

// 3. clone all edges
for (UndirectedGraphNode tmp : nodes) {
UndirectedGraphNode newNode = map.get(tmp);
for (UndirectedGraphNode n : tmp.neighbors) {
newNode.neighbors.add(map.get(n));
}
}

return map.get(node);
}
}


127. Topological Sorting

拓扑排序,把一个有向无环图转换成一维的拓扑排序。拓扑排序是对有向无环图的一种排序。表示了顶点按边的方向出现的先后顺序。如果有环,则无法表示两个顶点的先后顺序。一个简单的求拓扑排序的算法:首先要找到任意入度为0的一个顶点,删除它及所有相邻的边,再找入度为0的顶点,以此类推,直到删除所有顶点。顶点的删除顺序即为拓扑排序。这里要用到BFS。

1)首先计算每个点的入度。

2)把入度为0的节点加进队列。

3)用队列进行BFS操作,每次从队列中拿出节点的时候,更新它的后继结点的入度(后继结点入度减1)。

/**
* Definition for Directed graph.
* class DirectedGraphNode {
*     int label;
*     ArrayList<DirectedGraphNode> neighbors;
*     DirectedGraphNode(int x) { label = x; neighbors = new ArrayList<DirectedGraphNode>(); }
* };
*/
public class Solution {
/**
* @param graph: A list of Directed graph node
* @return: Any topological order for the given graph.
*/
public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
// calculate in-degree of all nodes
HashMap<DirectedGraphNode, Integer> map = new HashMap();
for (DirectedGraphNode node : graph) {
for (DirectedGraphNode neighbor : node.neighbors) {
if (map.containsKey(neighbor)) {
map.put(neighbor, map.get(neighbor) + 1);
} else {
map.put(neighbor, 1);
}
}
}

// add nodes with 0 in-degrees into the queue and result array
ArrayList<DirectedGraphNode> res = new ArrayList<DirectedGraphNode>();
Queue<DirectedGraphNode> q = new LinkedList<DirectedGraphNode>();
for (DirectedGraphNode node : graph) {
if (!map.containsKey(node)) {
q.offer(node);
res.add(node);
}
}

// BFS
while (!q.isEmpty()) {
DirectedGraphNode node = q.poll();
for (DirectedGraphNode neighbor : node.neighbors) {
map.put(neighbor, map.get(neighbor) - 1);
if (map.get(neighbor) == 0) {
q.offer(neighbor);
res.add(neighbor);
}
}
}

return res;
}
}


如果要用DFS的话,参考这个博客http://www.geeksforgeeks.org/topological-sorting/

120. Word Ladder

Given: start = "hit" end = "cog" dict = ["hot","dot","dog","lot","log"] As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.

根据一定的单词变化规则,看从起始单词能不能经过这个规则变到终止单词,并求出最少通过多少次能变到。规则就是每次只能变动一个字母,并且变动完后的单词要在给定的字典中。如果把整个变化的过程用图画出来,会发现这其实是一个graph,而求最少的次数,求相当于求最短路径的长度。有点像求二叉树的最小高度,使用的是BFS层次遍历,用到队列和hashset,用到hashset的原因是把每次走过的点标记为已走过,防止再重复走。



需要注意对边界情况做处理,比如字典为空,比如初始单词和终止单词是一个单词。还有就是要先把队列大小size的值给用一个变量保存一下,因为每次出队列都会使得队列的size发生变化,为了使得每个点都能遍历到,一定要用中间变量保存一下size

private String replace(String s, int index, char c) {
char[] arr = s.toCharArray();
arr[index] = c;
return new String(arr);
}
private ArrayList<String> findNeighbor(String word, Set<String> dict) {
ArrayList<String> res = new ArrayList<String>();
for (int i = 0; i < word.length(); i++) {
for (char c = 'a'; c <= 'z'; c++) {
if (word.charAt(i) != c) {
String tmp = replace(word, i, c);
if (dict.contains(tmp)) {
res.add(tmp);
}
}
}
}
return res;
}
public int ladderLength(String start, String end, Set<String> dict) {
if (dict == null) {
return 0;
}
if (start.equals(end)) {
return 1;
}
dict.add(start);
dict.add(end);

Queue<String> q = new LinkedList<String>();
HashSet<String> hash = new HashSet<String>();
q.offer(start);
hash.add(start);
int length = 1;

while (!q.isEmpty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
String word = q.poll();
for (String str : findNeighbor(word, dict)) {
if (hash.contains(str)) {
continue;
}
if (str.equals(end)) {
return length + 1;
}
hash.add(str);
q.offer(str);
}
}
length++;
}
return 0;
}


121. Word Ladder II
这道题跟上道题类似,不过要求的不只是最短路径了,而是要把最短路径的多种可能组合都给返回。如果要求出所有的组合,这种题目一般是DFS。如果是求最短路,则是BFS。所以这道题的解法是BFS+DFS。

BFS主要就做2件事情:

1)标记每个点(单词)的位置,越靠近起始单词,数字就越小,越靠近终止单词,数字就越大。比如起始单词的位置为0

2)对于每个单词,求出有哪些单词可以直接到达它,也就是求每个单词的父节点。

DFS就是从终止节点到起始节点进行DFS。一旦找到了起始节点,就可以把路径上经过的节点加入res里了。若还未找到节点,则继续把当前节点加入res里。

public List<List<String>> findLadders(String start, String end, Set<String> dict) {
List<List<String>> res = new ArrayList();
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
HashMap<String, Integer> distance = new HashMap<String, Integer>();

dict.add(start);
dict.add(end);

bfs(start, end, dict, map, distance);
dfs(res, new ArrayList<String>(), start, end, map, distance);
return res;
}

private ArrayList<String> findNeighbor(String word, Set<String> dict) {
ArrayList<String> res = new ArrayList<String>();
for (int i = 0; i < word.length(); i++) {
for (char c = 'a'; c <= 'z'; c++) {
if (word.charAt(i) != c) {
String tmp = word.substring(0, i) + c + word.substring(i+1);
if (dict.contains(tmp)) {
res.add(tmp);
}
}
}
}
return res;
}

private void bfs(String start, String end, Set<String> dict, HashMap<String, List<String>> map, HashMap<String, Integer> distance) {
Queue<String> q = new LinkedList<String>();
q.offer(start);
distance.put(start, 0);

while (!q.isEmpty()) {
String father = q.poll();
for (String str : findNeighbor(father, dict)) {
if (map.get(str) == null) {
ArrayList<String> tmp = new ArrayList<String>();
tmp.add(father);
map.put(str, tmp);
} else {
map.get(str).add(father);
}
// distance同时起到了判断有没有访问过的作用
if (!distance.containsKey(str)) {
q.offer(str);
distance.put(str, distance.get(father) + 1);
}
}
}
}

private void dfs(List<List<String>> res, List<String> path, String start, String end, HashMap<String, List<String>> map, HashMap<String, Integer> distance) {
if (end.equals(start)) {
path.add(start);
Collections.reverse(path);
res.add(new ArrayList<String>(path));
Collections.reverse(path);
path.remove(path.size() - 1);
return;
}
for (String next : map.get(end)) {
if (distance.get(next) + 1 == distance.get(end)) {
path.add(end);
dfs(res, path, start, next, map, distance);
path.remove(path.size() - 1);
}
}
}


531. Six Degrees
就是直接用BFS找最短长度。但是把HashMap换成HashSet就过不了了,需要注意的是,对于图来说,它的BFS的层次遍历,不能像树那样求高度那样每次length++。树是有规律的,从上到下是填满的,但是图就不一样了,所以要求路径长度,一定要根据它的上一个节点的长度+1.

/**
* Definition for Undirected graph.
* class UndirectedGraphNode {
*     int label;
*     List<UndirectedGraphNode> neighbors;
*     UndirectedGraphNode(int x) {
*         label = x;
*         neighbors = new ArrayList<UndirectedGraphNode>();
*     }
* };
*/
public class Solution {
/**
* @param graph a list of Undirected graph node
* @param s, t two Undirected graph nodes
* @return an integer
*/
public int sixDegrees(List<UndirectedGraphNode> graph,
UndirectedGraphNode s,
UndirectedGraphNode t) {
if (s == t) {
return 0;
}
Queue<UndirectedGraphNode> q = new LinkedList<UndirectedGraphNode>();
HashMap<UndirectedGraphNode, Integer> hash = new HashMap<UndirectedGraphNode, Integer>();
q.offer(s);
hash.put(s, 0);

int distance = 0;
while(!q.isEmpty()) {
UndirectedGraphNode head = q.poll();
int size = head.neighbors.size();
for (int i = 0; i < size; i++) {
UndirectedGraphNode node = head.neighbors.get(i);
if (hash.containsKey(node)) {
continue;
}
if (node == t) {
return hash.get(head) + 1;
}
q.offer(node);
hash.put(node, hash.get(head) + 1);
}
}
return -1;
}
}


431. Find the Connected Component in the Undirected Graph
找出无向图中所有的连通块,这道题好像就是Coursera上普林斯顿的算法课的练习题,有两种方法可以做,一种是并查集,还有一种就是BFS。

/**
* Definition for Undirected graph.
* class UndirectedGraphNode {
*     int label;
*     ArrayList<UndirectedGraphNode> neighbors;
*     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
* };
*/
public class Solution {
/**
* @param nodes a array of Undirected graph node
* @return a connected set of a Undirected graph
*/
public void bfs(List<List<Integer>> res, Set<UndirectedGraphNode> set, UndirectedGraphNode node) {
Queue<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>();
List<Integer> list = new ArrayList<Integer>();
list.add(node.label);
queue.offer(node);
set.add(node);

while (!queue.isEmpty()) {
UndirectedGraphNode head = queue.poll();
List<UndirectedGraphNode> next = head.neighbors;
for (UndirectedGraphNode nextNode: next) {
if (!set.contains(nextNode)) {
list.add(nextNode.label);
set.add(nextNode);
queue.offer(nextNode);
}
}
}
Collections.sort(list);
res.add(list);
}

public List<List<Integer>> connectedSet(ArrayList<UndirectedGraphNode> nodes) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
Set<UndirectedGraphNode> set = new HashSet<UndirectedGraphNode>();

for (UndirectedGraphNode node: nodes) {
if (!set.contains(node)) {
bfs(res, set, node);
}
}
return res;
}
}


176. Route Between Two Nodes in Graph

在一个有向图里,问2个点是否是连通的。典型的BFS题,用BFS遍历,如果中途遇到了另外一个点,这说明可到达,否则不可达。

public boolean hasRoute(ArrayList<DirectedGraphNode> graph,
DirectedGraphNode s, DirectedGraphNode t) {
HashSet<DirectedGraphNode> visit = new HashSet();
Queue<DirectedGraphNode> q = new LinkedList();

if (t == s) {
return true;
}

q.offer(s);
while (!q.isEmpty()) {
DirectedGraphNode head = q.poll();
ArrayList<DirectedGraphNode> arr = head.neighbors;
for (DirectedGraphNode next : arr) {
if (!visit.contains(next)) {
if (next == t) {
return true;
}
visit.add(next);
q.offer(next);
} else {
continue;
}
}
}
return false;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LintCode Graph Search DFS BFS