深度优先搜索和广度优先搜索

视频教程:B站、网易云课堂、腾讯课堂
代码地址:Gitee、Github
存储地址:
百度云-提取码:
Google云

补充:递归并不意味着效率差,主要可能是因为没有用缓存,等等原因

树节点:

python版:
class TreeNode:
  def __init__(self,val):
    self.val = val
    self.left,self.right = None,None

C++版:
struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x):val(x),left(NULL),right(NULL){} 
}

Java版:
public class TreeNode {
  public int val;
  public TreeNode left,right;
  public TreeNode(int val){
    this.val = val;
    this.left = null;
    this.right = null;
   }
}

在这里插入图片描述
Python版不同的遍历:

def preorder(self,root):
   if root:
       self.traverse_path.append(root.val)
       self.preorder(root.left)
       self.preorder(root.right)
       
def inorder(self,root):
   if root:
       self.preorder(root.left)
       self.traverse_path.append(root.val)
       self.preorder(root.right)

def postorder(self,root):
   if root:
       self.preorder(root.left)
       self.preorder(root.right)
       self.traverse_path.append(root.val)

常见操作:查询、插入、删除

树的面试题或者大部分问题,用的都是递归,主要是因为树的结构是由左右子节点构成的原因,使用递归会更加简单便捷

  1. 二叉树的层序遍历

国内站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/

public class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        List<List<Integer>> wrapList = new LinkedList<List<Integer>>();
        
        if(root == null) return wrapList;
        
        queue.offer(root);
        while(!queue.isEmpty()){
            int levelNum = queue.size();
            List<Integer> subList = new LinkedList<Integer>();
            for(int i=0; i<levelNum; i++) {
                if(queue.peek().left != null) queue.offer(queue.peek().left);
                if(queue.peek().right != null) queue.offer(queue.peek().right);
                subList.add(queue.poll().val);
            }
            wrapList.add(subList);
        }
        return wrapList;
    }
}


/*
评价:
优点:
缺点:
*/

在这里插入图片描述

python版:



'''
思路:

'''


class Solution(object):
    def levelOrder(self, root):
        res = []
        self.dfs(root, 0, res)
        return res
        
    def dfs(self, root, level, res):
        if not root:
            return 
        if len(res) < level+1:
            res.append([])
        res[level].append(root.val)
        self.dfs(root.left, level+1, res)
        self.dfs(root.right, level+1, res)


'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/

class Solution {
public:
    vector<vector<int> > levelOrder(TreeNode *root) {
        vector<vector<int> >  result;
        if (!root) return result;
        queue<TreeNode*> q;
        q.push(root);
        q.push(NULL);
        vector<int> cur_vec;
        while(!q.empty()) {
            TreeNode* t = q.front();
            q.pop();
            if (t==NULL) {
                result.push_back(cur_vec);
                cur_vec.resize(0);
                if (q.size() > 0) {
                    q.push(NULL);
                }
            } else {
                cur_vec.push_back(t->val);
                if (t->left) q.push(t->left);
                if (t->right) q.push(t->right);
            }
        }
        return result;
    }
};
/*
评价:
优点:
缺点:
*/

  1. 最小基因变化

国内站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/

public class Solution {
    public int minMutation(String start, String end, String[] bank) {
        if(start.equals(end)) return 0;
        
        Set<String> bankSet = new HashSet<>();
        for(String b: bank) bankSet.add(b);
        
        char[] charSet = new char[]{'A', 'C', 'G', 'T'};
        
        int level = 0;
        Set<String> visited = new HashSet<>();
        Queue<String> queue = new LinkedList<>();
        queue.offer(start);
        visited.add(start);
        
        while(!queue.isEmpty()) {
            int size = queue.size();
            while(size-- > 0) {
                String curr = queue.poll();
                if(curr.equals(end)) return level;
                
                char[] currArray = curr.toCharArray();
                for(int i = 0; i < currArray.length; i++) {
                    char old = currArray[i];
                    for(char c: charSet) {
                        currArray[i] = c;
                        String next = new String(currArray);
                        if(!visited.contains(next) && bankSet.contains(next)) {
                            visited.add(next);
                            queue.offer(next);
                        }
                    }
                    currArray[i] = old;
                }
            }
            level++;
        }
        return -1;
    }
}


/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

  1. 括号生成

国内站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> list = new ArrayList<String>();
        backtrack(list,"",0,0,n);
        return list;
    }
    public void backtrack(List<String> list,String str,int open,int close,int max) {
        if (str.length() == max*2 ) {
            list.add(str);
            return;
        }
        if (open <max ) 
            backtrack(list,str+"(",open+1,close,max);
        
        if (close <open ) 
               backtrack(list,str+")",open,close+1,max);
        
    }
}



/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

  1. 在每个树行中找最大值
    国内站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/

public class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        helper(root, res, 0);
        return res;
    }
    private void helper(TreeNode root, List<Integer> res, int d){
        if(root == null){
            return;
        }
       //expand list size
        if(d == res.size()){
            res.add(root.val);
        }
        else{
        //or set value
            res.set(d, Math.max(res.get(d), root.val));
        }
        helper(root.left, res, d+1);
        helper(root.right, res, d+1);
    }
}


/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

  1. 单词接龙

国内站

java版

/*
思路:

*/

class Solution {
  public int ladderLength(String beginWord, String endWord, List<String> wordList) {

    // Since all words are of same length.
    int L = beginWord.length();

    // Dictionary to hold combination of words that can be formed,
    // from any given word. By changing one letter at a time.
    Map<String, List<String>> allComboDict = new HashMap<>();

    wordList.forEach(
        word -> {
          for (int i = 0; i < L; i++) {
            // Key is the generic word
            // Value is a list of words which have the same intermediate generic word.
            String newWord = word.substring(0, i) + '*' + word.substring(i + 1, L);
            List<String> transformations = allComboDict.getOrDefault(newWord, new ArrayList<>());
            transformations.add(word);
            allComboDict.put(newWord, transformations);
          }
        });

    // Queue for BFS
    Queue<Pair<String, Integer>> Q = new LinkedList<>();
    Q.add(new Pair(beginWord, 1));

    // Visited to make sure we don't repeat processing same word.
    Map<String, Boolean> visited = new HashMap<>();
    visited.put(beginWord, true);

    while (!Q.isEmpty()) {
      Pair<String, Integer> node = Q.remove();
      String word = node.getKey();
      int level = node.getValue();
      for (int i = 0; i < L; i++) {

        // Intermediate words for current word
        String newWord = word.substring(0, i) + '*' + word.substring(i + 1, L);

        // Next states are all the words which share the same intermediate state.
        for (String adjacentWord : allComboDict.getOrDefault(newWord, new ArrayList<>())) {
          // If at any point if we find what we are looking for
          // i.e. the end word - we can return with the answer.
          if (adjacentWord.equals(endWord)) {
            return level + 1;
          }
          // Otherwise, add it to the BFS Queue. Also mark it visited
          if (!visited.containsKey(adjacentWord)) {
            visited.put(adjacentWord, true);
            Q.add(new Pair(adjacentWord, level + 1));
          }
        }
      }
    }

    return 0;
  }
}


/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

  1. 单词接龙 II

国内站

java版

/*
思路:

*/

class Solution {
    private static final int INF = 1 << 20;
    private Map<String, Integer> wordId; // 单词到id的映射
    private ArrayList<String> idWord; // id到单词的映射
    private ArrayList<Integer>[] edges; // 图的边

    public Solution() {
        wordId = new HashMap<>();
        idWord = new ArrayList<>();
    }

    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        int id = 0;
        // 将wordList所有单词加入wordId中 相同的只保留一个 // 并为每一个单词分配一个id
        for (String word : wordList) {
            if (!wordId.containsKey(word)) { 
                wordId.put(word, id++);
                idWord.add(word);
            }
        }
        // 若endWord不在wordList中 则无解
        if (!wordId.containsKey(endWord)) {
            return new ArrayList<>();
        }
        // 把beginWord也加入wordId中
        if (!wordId.containsKey(beginWord)) {
            wordId.put(beginWord, id++);
            idWord.add(beginWord);
        }

        // 初始化存边用的数组
        edges = new ArrayList[idWord.size()];
        for (int i = 0; i < idWord.size(); i++) {
            edges[i] = new ArrayList<>();
        }
        // 添加边
        for (int i = 0; i < idWord.size(); i++) {
            for (int j = i + 1; j < idWord.size(); j++) {
                // 若两者可以通过转换得到 则在它们间建一条无向边
                if (transformCheck(idWord.get(i), idWord.get(j))) {
                    edges[i].add(j);
                    edges[j].add(i);
                }
            }
        }

        int dest = wordId.get(endWord); // 目的ID
        List<List<String>> res = new ArrayList<>(); // 存答案
        int[] cost = new int[id]; // 到每个点的代价
        for (int i = 0; i < id; i++) {
            cost[i] = INF; // 每个点的代价初始化为无穷大
        }

        // 将起点加入队列 并将其cost设为0
        Queue<ArrayList<Integer>> q = new LinkedList<>();
        ArrayList<Integer> tmpBegin = new ArrayList<>();
        tmpBegin.add(wordId.get(beginWord));
        q.add(tmpBegin);
        cost[wordId.get(beginWord)] = 0;

        // 开始广度优先搜索
        while (!q.isEmpty()) {
            ArrayList<Integer> now = q.poll();
            int last = now.get(now.size() - 1); // 最近访问的点
            if (last == dest) { // 若该点为终点则将其存入答案res中
                ArrayList<String> tmp = new ArrayList<>();
                for (int index : now) {
                    tmp.add(idWord.get(index)); // 转换为对应的word
                }
                res.add(tmp);
            } else { // 该点不为终点 继续搜索
                for (int i = 0; i < edges[last].size(); i++) {
                    int to = edges[last].get(i);
                    // 此处<=目的在于把代价相同的不同路径全部保留下来
                    if (cost[last] + 1 <= cost[to]) {
                        cost[to] = cost[last] + 1;
                        // 把to加入路径中
                        ArrayList<Integer> tmp = new ArrayList<>(now); tmp.add(to);
                        q.add(tmp); // 把这个路径加入队列
                    }
                }
            }
        }
        return res;
    }

    // 两个字符串是否可以通过改变一个字母后相等
    boolean transformCheck(String str1, String str2) {
        int differences = 0;
        for (int i = 0; i < str1.length() && differences < 2; i++) {
            if (str1.charAt(i) != str2.charAt(i)) {
                ++differences;
            }
        }
        return differences == 1;
    } 
}




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

  1. 岛屿数量

国内站

java版

/*
思路:

*/

class Solution {
    void dfs(char[][] grid, int r, int c) {
        int nr = grid.length;
        int nc = grid[0].length;

        if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0') {
            return;
        }

        grid[r][c] = '0';
        dfs(grid, r - 1, c);
        dfs(grid, r + 1, c);
        dfs(grid, r, c - 1);
        dfs(grid, r, c + 1);
    }

    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0) {
            return 0;
        }

        int nr = grid.length;
        int nc = grid[0].length;
        int num_islands = 0;
        for (int r = 0; r < nr; ++r) {
            for (int c = 0; c < nc; ++c) {
                if (grid[r][c] == '1') {
                    ++num_islands;
                    dfs(grid, r, c);
                }
            }
        }

        return num_islands;
    }
}




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

  1. 扫雷游戏

国内站

java版

/*
思路:

*/




/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

国外站

java版

/*
思路:

*/


public class Solution {
    public char[][] updateBoard(char[][] board, int[] click) {
        int m = board.length, n = board[0].length;
        int row = click[0], col = click[1];
        
        if (board[row][col] == 'M') { // Mine
            board[row][col] = 'X';
        }
        else { // Empty
            // Get number of mines first.
            int count = 0;
            for (int i = -1; i < 2; i++) {
                for (int j = -1; j < 2; j++) {
                    if (i == 0 && j == 0) continue;
                    int r = row + i, c = col + j;
                    if (r < 0 || r >= m || c < 0 || c < 0 || c >= n) continue;
                    if (board[r][c] == 'M' || board[r][c] == 'X') count++;
                }
            }
            
            if (count > 0) { // If it is not a 'B', stop further DFS.
                board[row][col] = (char)(count + '0');
            }
            else { // Continue DFS to adjacent cells.
                board[row][col] = 'B';
                for (int i = -1; i < 2; i++) {
                    for (int j = -1; j < 2; j++) {
                        if (i == 0 && j == 0) continue;
                        int r = row + i, c = col + j;
                        if (r < 0 || r >= m || c < 0 || c < 0 || c >= n) continue;
                        if (board[r][c] == 'E') updateBoard(board, new int[] {r, c});
                    }
                }
            }
        }
        
        return board;
    }
}


/*
评价:
优点:
缺点:
*/

python版:



'''
思路:

'''

'''
评价:
  优点:
  缺点:
'''

c++版:

/*
思路:

*/


/*
评价:
优点:
缺点:
*/

一 深度优先搜索、广度优先搜索的实现和特性

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二 实战题目解析:二叉树的层次遍历等问题

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值