LeetCode刷题笔记-BFS&DFS

97 阅读4分钟

广度优先搜索

127 Word Ladder Medium

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

Only one letter can be changed at a time.

Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

Note:

Return 0 if there is no such transformation sequence.

All words have the same length.

All words contain only lowercase alphabetic characters.

You may assume no duplicates in the word list.

You may assume beginWord and endWord are non-empty and are not the same.

Example 1:

Input:

beginWord = "hit",

endWord = "cog",

wordList = ["hot","dot","dog","lot","log","cog"]

Output: 5

Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",

return its length 5.

Example 2:

Input:

beginWord = "hit"

endWord = "cog"

wordList = ["hot","dot","dog","lot","log"]

Output: 0

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

思路:套用BFS同时利用BFS能寻找最短路径的特性解决问题。参考

把每个单词作为一个node进行BFS。当取得当前字符串时,对他的每一位字符进行从az的替换,如果在字典里面,就入队,并且为了避免环路,需把在字典里检测到的单词从字典里删除。这样对于当前字符串的每一位字符按照az替换后,在queue中的单词就作为下一层需要遍历的单词。

因为BFS能够把一层所有可能性都遍历了,所以就保证了一旦找到一个单词equals(end),那么return的路径肯定是最短的。

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        if(beginWord.length() != endWord.length() || wordList == null || !wordList.contains(endWord)) {
            return 0;
        }
        Set<String> wordSet = new HashSet(wordList);    // 关键!!否则一直TLE。。。
        LinkedList<String> queue = new LinkedList<>();
        queue.add(beginWord);
        int level = 1;
        while(queue.size()!=0) {
            int count = queue.size();
            for(int i=0; i<count; i++) {
                String word = queue.remove();
                for(int j=0; j<word.length(); j++) {
                    char[] wordArray = word.toCharArray();
                    for(char ch='a'; ch<='z'; ch++) {
                        wordArray[j] = ch;
                        String newStr = new String(wordArray);
                        if(newStr.equals(endWord)) {
                            return level+1;
                        }
                        if(wordSet.contains(newStr)) {
                            queue.add(newStr);
                            wordSet.remove(newStr);
                        }
                    }
                }
            }
            level++;
        }
        return 0;
    }    
}

双向BFS解法:

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        if(beginWord.length()!=endWord.length() || wordList == null || !wordList.contains(endWord)) {
            return 0;
        }
        Set<String> wordSet = new HashSet(wordList);

        Set<String> beginSet = new HashSet<>();
        Set<String> endSet = new HashSet<>();
        beginSet.add(beginWord);
        endSet.add(endWord);

        int level = 1;
        while(!beginSet.isEmpty() && !endSet.isEmpty()) {
            if(beginSet.size() > endSet.size()) {
                Set<String> temp = beginSet;
                beginSet = endSet;
                endSet = temp;
            }

            Set<String> set = new HashSet<>();
            for(String word:beginSet) {               
                for(int j=0; j<word.length(); j++) {
                    char[] wordArray = word.toCharArray();
                    for(char ch='a'; ch<='z'; ch++) {
                        wordArray[j] = ch;
                        String newStr = new String(wordArray);
                        if(endSet.contains(newStr)) {
                            return level+1;
                        }
                        if(wordSet.contains(newStr)) {
                            set.add(newStr);
                            wordSet.remove(newStr);
                        }
                    }
                }
            }
            beginSet = set;
            level++;
        }
        return 0;
    }    
}

深度优先搜索

784 Letter Case Permutation Medium

Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. Return a list of all possible strings we could create.

Examples:

Input: S = "a1b2"

Output: ["a1b2", "a1B2", "A1b2", "A1B2"]

Input: S = "3z4"

Output: ["3z4", "3Z4"]

Input: S = "12345"

Output: ["12345"]

Note:

S will be a string with length at most 12.

S will consist only of letters or digits.

image.png

class Solution {
    public List<String> letterCasePermutation(String S) {
        List<String> ans = new ArrayList<>();
        char[] chars = S.toCharArray();
        dfs(chars, 0, ans);
        return ans;
    }

    private void dfs(char[] chars, int loc, List<String> ans) {
        if (loc == chars.length) {
            ans.add(new String(chars));
            return;
        }
        dfs(chars, loc + 1, ans);
        if (Character.isLetter(chars[loc])) {
            chars[loc] ^= 1 << 5;
            dfs(chars, loc + 1, ans);
            chars[loc] ^= 1 << 5;
        }
    }
}

131 Palindrome Partitioning Medium

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

Example:

Input: "aab"

Output:

[

["aa","b"],

["a","a","b"]

]

class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> result = new ArrayList<>();
        List<String> record = new ArrayList<>();
        dfs(s, 0, record, result);
        return result;
    }

    // 从start开始
    private void dfs(String s, int start, List<String> record, List<List<String>> result) {
        if (start == s.length()) {
            result.add(new ArrayList<>(record));    // 不能add引用,必须new一个
            return;
        }
        for (int i = start; i < s.length(); i++) {
            // 在i+1处砍断
            if (isPalindrome(s.substring(start, i+1))) {
                record.add(s.substring(start, i+1));
                dfs(s, i+1, record, result);
                // 回溯
                record.remove(record.size() - 1);
            }
        }
    }

    private boolean isPalindrome(String s) {
        if(s == null || s.length() == 0) {
            return false;
        }
        int i = 0, j = s.length() - 1;
        while (i < j) {
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }
}

77 Combinations Medium

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

Example:

Input: n = 4, k = 2

Output:

[

[2,4],

[3,4],

[2,3],

[1,2],

[1,3],

[1,4],

]

public List<List<Integer>> combine(int n, int k) {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> item = new ArrayList<>();
    dfs(n, k, 1, 0, item, result);
    return result;
}

/**
 * @param n
 * @param k
 * @param start 开始的数
 * @param count 已经选择的个数
 * @param item
 * @param result
 */
private void dfs(int n, int k, int start, int count, List<Integer> item, List<List<Integer>> result) {
    if (count == k) {
        result.add(new ArrayList<>(item));
        return;
    }
    for (int i = start; i <= n; i++) {
        item.add(i);
        dfs(n, k, i + 1, count + 1, item, result);
        // 回溯
        item.remove(item.size() - 1);
    }
}

39 Combination Sum Medium

Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

The same repeated number may be chosen from candidates unlimited number of times.

Note:

All numbers (including target) will be positive integers.

The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [2,3,6,7], target = 7,

A solution set is:

[

[7],

[2,2,3]

]

Example 2:

Input: candidates = [2,3,5], target = 8,

A solution set is:

[

[2,2,2,2],

[2,3,3],

[3,5]

]

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> item = new ArrayList<>();
        Set<List<Integer>> set = new HashSet<>();
        dfs(candidates, target, 0, 0, item, set);
        return new ArrayList<>(set);
    }

    private void dfs(int[] candidates, int target, int start, int sum, List<Integer> item, Set<List<Integer>> result) {
        if (sum == target) {
            result.add(new ArrayList<>(item));
            return;
        }
        for (int i = start; i < candidates.length; i++) {
            // 剪枝:加上这个数超过目标和,后面的数就不用试了
            if(sum + candidates[i] > target) {
                return;
            }
            item.add(candidates[i]);
            dfs(candidates, target, i, sum + candidates[i], item, result);
            // 回溯
            item.remove(item.size() - 1);
        }
    }
}