深度优先搜索(DFS) — 20180926

Posted lizzyluvcoding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度优先搜索(DFS) — 20180926相关的知识,希望对你有一定的参考价值。

用DFS的场景:

找出所有方案:DFS
找出所有方案总数 可能是动态规划

DFS时间复杂度:答案个数*构造每个答案的时间

动态规划时间复杂度:状态个数*计算每个状态时间

二叉树时间复杂度:节点数*处理每个节点时间

135. Combination Sum

技术分享图片
 1 public class Solution {
 2     /**
 3      * @param candidates: A list of integers
 4      * @param target: An integer
 5      * @return: A list of lists of integers
 6      */
 7     public List<List<Integer>> combinationSum(int[] candidates, int target) {
 8         // write your code here
 9         List<List<Integer>> result = new ArrayList<>();
10         if(candidates ==  null || candidates.length ==0){
11             return result;   
12         }
13         Arrays.sort(candidates);
14         ArrayList<Integer> combination = new ArrayList<>();
15         
16         Hepler(result,candidates,target,0,combination);
17         return result;
18         
19     }
20     
21     
22     public void Hepler(List<List<Integer>> result,int[] candidates, int target, int startIndex,List<Integer> combination){
23         if(target == 0){
24             result.add(new ArrayList(combination));
25             return;
26         }
27         
28         for(int i= startIndex; i<candidates.length; i++){
29             if(target<candidates[i]){
30                 continue;
31             }
32             if(i>0 && candidates[i]==candidates[i-1]){
33                 continue;
34             }
35             combination.add(candidates[i]);
36             Hepler(result,candidates,target-candidates[i],i,combination);
37             combination.remove(combination.size()-1);
38         }
39     }
40 }
View Code

 

153. Combination Sum II

技术分享图片
 1 public class Solution {
 2     /**
 3      * @param num: Given the candidate numbers
 4      * @param target: Given the target number
 5      * @return: All the combinations that sum to target
 6      */
 7     public List<List<Integer>> combinationSum2(int[] num, int target) {
 8         // write your code here
 9         List<List<Integer>> result = new ArrayList<>();
10         if(num == null || num.length ==0){
11             return result;
12         }
13         Arrays.sort(num);
14         List<Integer> combination = new ArrayList<>();
15         
16         Helper(num,target,0,result,combination);
17         
18         return result;
19     }
20     
21     public void Helper(int[] num, int target, int startIndex, List<List<Integer>> result, List<Integer> combination){
22         if(target==0){
23             result.add(new ArrayList<>(combination));
24             return;
25         }
26         
27         for(int i = startIndex; i<num.length; i++){
28             if(target<num[i]){
29                 break;
30             }
31             if(i>0 && num[i] == num[i-1] && i!=startIndex){
32                 continue;
33             }
34             combination.add(num[i]);
35             Helper(num,target-num[i],i+1,result,combination);
36             combination.remove(combination.size()-1);
37         }
38     }
39 }
View Code

 

136. Palindrome Partitioning

切割问题也就是组合问题

技术分享图片
 1 public class Solution {
 2     /*
 3      * @param s: A string
 4      * @return: A list of lists of string
 5      */
 6     public List<List<String>> partition(String s) {
 7         // write your code here
 8         List<List<String>> result = new ArrayList<>();
 9         if (s == null || s.length() == 0) {
10             return result;
11         }
12 
13         List<String> combination = new ArrayList<>();
14         Helper(result, combination, 0, s);
15         return result;
16     }
17 
18     public void Helper(List<List<String>> result, List<String> combination, int startIndex, String s) {
19         if (startIndex == s.length()) {
20             result.add(new ArrayList<>(combination));
21             return;
22         }
23 
24         for (int i = startIndex; i < s.length(); i++) {
25             String sub = s.substring(startIndex, i + 1);
26             if (!isPalindrome(sub)) {
27                 continue;
28             }
29             combination.add(sub);
30             Helper(result, combination, i + 1, s);
31             combination.remove(combination.size() - 1);
32         }
33     }
34 
35     public boolean isPalindrome(String s) {
36         int start = 0;
37         int end = s.length() - 1;
38         while (start < end) {
39             if (s.charAt(start) != s.charAt(end)) {
40                 return false;
41             }
42             start++;
43             end--;
44         }
45         return true;
46     }
47 }
View Code

 

15. Permutations

技术分享图片
 1 public class Solution {
 2     /*
 3      * @param nums: A list of integers.
 4      * @return: A list of permutations.
 5      */
 6     public List<List<Integer>> permute(int[] nums) {
 7         // write your code here
 8         List<List<Integer>> result = new ArrayList<>();
 9         if (nums == null) {
10             return result;
11         }
12 
13         boolean[] visited = new boolean[nums.length];
14         List<Integer> permutation = new ArrayList<>();
15         Helper(result, permutation, nums, visited);
16         return result;
17     }
18 
19     public void Helper(List<List<Integer>> result, List<Integer> permutation, int[] nums, boolean[] visited) {
20         if (permutation.size() == nums.length) {
21             result.add(new ArrayList<>(permutation));
22             return;
23         }
24 
25         for (int i = 0; i < nums.length; i++) {
26             if (visited[i]) {
27                 continue;
28             }
29             permutation.add(nums[i]);
30             visited[i] = true;
31             Helper(result, permutation, nums, visited);
32             permutation.remove(permutation.size() - 1);
33             visited[i] = false;
34         }
35     }
36 }
View Code

 

16. Permutations II

技术分享图片
 1 public class Solution {
 2     /*
 3      * @param :  A list of integers
 4      * @return: A list of unique permutations
 5      */
 6     public List<List<Integer>> permuteUnique(int[] nums) {
 7         // write your code here
 8         List<List<Integer>> result = new ArrayList<>();
 9         if(nums == null){
10             return result;
11         }
12 
13         List<Integer> permutation = new ArrayList<>();
14         boolean[] visited =new boolean[nums.length];
15         Arrays.sort(nums);
16         Helper(result,nums,permutation,visited);
17         return  result;
18     }
19 
20     public void Helper(List<List<Integer>> result, int[] nums, List<Integer> permutation, boolean[] visited){
21         if(permutation.size() == nums.length){
22             result.add(new ArrayList<>(permutation));
23             return;
24         }
25 
26         for(int i =0; i<nums.length;i++){
27             if(visited[i]){
28                 continue;
29             }
30             if(i>0 && nums[i]==nums[i-1] && visited[i-1] == false){
31                 continue;
32             }
33             permutation.add(nums[i]);
34             visited[i] = true;
35             Helper(result,nums,permutation,visited);
36             permutation.remove(permutation.size()-1);
37             visited[i] = false;
38         }
39     }
40 };
View Code

 

33. N-Queens

技术分享图片
 1 public class Solution {
 2     /*
 3      * @param n: The number of queens
 4      * @return: All distinct solutions
 5      */
 6     public List<List<String>> solveNQueens(int n) {
 7         // write your code here
 8         List<List<String>> result = new ArrayList<>();
 9         if (n < 0) {
10             return result;
11         }
12         List<Integer> queenSolution = new ArrayList<>();
13         Helper(result, queenSolution, n);
14         return result;
15     }
16 
17     public void Helper(List<List<String>> result, List<Integer> queenSolution, int n) {
18         if (queenSolution.size() == n) {
19             result.add(getQueenStr(queenSolution));
20             return;
21         }
22 
23         for (int i = 0; i < n; i++) {
24             if (!isValid(queenSolution, i)) {
25                 continue;
26             }
27             queenSolution.add(i);
28             Helper(result, queenSolution, n);
29             queenSolution.remove(queenSolution.size() - 1);
30         }
31     }
32 
33     public boolean isValid(List<Integer> queenSolution, int q) {
34         int nextcol = queenSolution.size();
35         for (int i = 0; i < queenSolution.size(); i++) {
36             //判断是否同一列
37             if (queenSolution.get(i) == q) {
38                 return false;
39             }
40             //判断是否在左斜线
41             if (nextcol + q == i + queenSolution.get(i)) {
42                 return false;
43             }
44             //判断是否在右斜线
45             if (nextcol - q == i - queenSolution.get(i)) {
46                 return false;
47             }
48         }
49 
50         return true;
51     }
52 
53     public List<String> getQueenStr(List<Integer> solution) {
54         List<String> res = new ArrayList<>();
55         int strLen = solution.size();
56         for (Integer i : solution) {
57             StringBuilder stringBuilder = new StringBuilder();
58             for (int m = 0; m < strLen; m++) {
59                 stringBuilder.append(m == i ? ‘Q‘ : ‘.‘);
60             }
61             res.add(stringBuilder.toString());
62         }
63         return res;
64     }
65 }
View Code

 

121. Word Ladder II

技术分享图片
  1 public class Solution {
  2     /*
  3      * @param start: a string
  4      * @param end: a string
  5      * @param dict: a set of string
  6      * @return: a list of lists of string
  7      */
  8     public List<List<String>> findLadders(String start, String end, Set<String> dict) {
  9         // write your code here
 10         List<List<String>> result = new ArrayList<>();
 11         if (start == null || end == null) {
 12             return result;
 13         }
 14         if (start.equals(end)) {
 15             List<String> solution = new ArrayList<>();
 16             solution.add(start);
 17             solution.add(end);
 18             result.add(solution);
 19             return result;
 20         }
 21         //字典要加入start,end,否则对某些case会fail
 22         dict.add(start);
 23         dict.add(end);
 24         Map<String, Integer> distanceMap = new HashMap<>();
 25         Map<String, List<String>> neighbourMap = new HashMap<>();
 26         getShortestPath(start, end, dict, distanceMap, neighbourMap);
 27         List<String> solution = new ArrayList<>();
 28         //基于nextWord进行递归,所以一开始要将初始值加入solution
 29         solution.add(start);
 30         Helper(result, solution, distanceMap, neighbourMap, start, end);
 31         return result;
 32     }
 33 
 34     //bfs 重点注意,得到最短路径之后一定要走完最后一层的BFS,否则会少解
 35     public void getShortestPath(String start, String end, Set<String> dict,
 36                                Map<String, Integer> distanceMap, Map<String, List<String>> neighbourMap) {
 37 
 38         Queue<String> queue = new LinkedList<>();
 39         queue.offer(start);
 40         distanceMap.put(start, 0);
 41 
 42         int distance = 0;
 43         boolean isShortedPath = false;
 44         while (!queue.isEmpty()) {
 45             int size = queue.size();
 46             distance++;
 47             for (int i = 0; i < size; i++) {
 48                 String word = queue.poll();
 49                 if (neighbourMap.containsKey(word)) {
 50                     continue;
 51                 }
 52                 neighbourMap.put(word, new ArrayList<>());
 53                 for (String next : getNextWords(word, dict)) {
 54                     neighbourMap.get(word).add(next);
 55                     if(!distanceMap.containsKey(next)){
 56                         distanceMap.put(next, distance);
 57                         queue.offer(next);
 58                     }
 59                     if (next.equals(end)) {
 60                         isShortedPath = true;
 61                     }
 62                 }
 63             }
 64             
 65             if(isShortedPath){
 66                 break;
 67             }
 68         }
 69 
 70     }
 71 
 72     //dfs
 73     public void Helper(List<List<String>> result, List<String> solution,
 74                        Map<String, Integer> distanceMap, Map<String, List<String>> neighbourMap,
 75                        String word, String end) {
 76         if(word.equals(end)){
 77             result.add(new ArrayList<>(solution));
 78             return;
 79         }
 80         
 81         if(neighbourMap.get(word)!=null){
 82             for(String str: neighbourMap.get(word)){
 83                 if(distanceMap.containsKey(str) && distanceMap.get(str) == distanceMap.get(word) + 1){
 84                     solution.add(str);
 85                     Helper(result,solution,distanceMap,neighbourMap,str,end);
 86                     solution.remove(solution.size()-1);
 87                 }
 88             }
 89         }
 90     }
 91 
 92     public List<String> getNextWords(String word, Set<String> dict) {
 93         List<String> result = new ArrayList<>();
 94         int len = word.length();
 95         for (int i = 0; i < len; i++) {
 96             for (char ch = ‘a‘; ch <= ‘z‘; ch++) {
 97                 if (ch == word.charAt(i)) {
 98                     continue;
 99                 }
100                 if (dict.contains(getReplaceWord(word, i, ch))) {
101                     result.add(getReplaceWord(word, i, ch));
102                 }
103             }
104         }
105         return result;
106     }
107 
108     public String getReplaceWord(String word, int i, char ch) {
109         char[] chars = word.toCharArray();
110         chars[i] = ch;
111         return new String(chars);
112     }
113 
114 }
View Code

 


以上是关于深度优先搜索(DFS) — 20180926的主要内容,如果未能解决你的问题,请参考以下文章

DFS(深度优先搜索遍历有向图)-03-有向图-太平洋大西洋水流问题

深度优先搜索(DFS: Depth First Search)

数据结构与算法图遍历算法 ( 深度优先搜索 DFS | 深度优先搜索和广度优先搜索 | 深度优先搜索基本思想 | 深度优先搜索算法步骤 | 深度优先搜索理论示例 )

深度优先搜索 DFS(Depath First Search, DFS)

LeetCode 988:回溯和深度优先搜索(DFS)的区别

DFS(深度优先搜索)