【算法集训 | 暑期刷题营】8.2 题---暴力递归之深搜

91 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

《算法集训传送门

  👉引言

铭记于心
🎉✨🎉我唯一知道的,便是我一无所知🎉✨🎉

💖 ❄️我们的算法之路❄️💖

   众所周知,作为一名合格的程序员,算法 能力 是不可获缺的,并且在算法学习的过程中我们总是能感受到算法的✨魅力✨。
☀️🌟短短几行代码,凝聚无数前人智慧;一个普通循环,即是解题之眼🌟☀️
💝二分,💝贪心,💝并查集,💝二叉树,💝图论,💝深度优先搜索(dfs) ,💝宽度优先搜索(bfs) ,💝数论,💝动态规划等等, 路漫漫其修远兮,吾将上下而求索! 希望在此集训中与大家共同进步,有所收获!!!🎉🎉🎉
在这里插入图片描述


今日主题:暴力深搜


 👉⭐️第一题💎

   ✨题目

       image.png

   ✨思路:

for循环+递归,先从那n个数中选取一个,用set进行标记(这里设置成一个数组进行标记更快,因为数组是支持随机访问的),然后递归剩下的数,注意回溯时要恢复现场(因为这里是引用,如果是按值传递的话则不需要恢复现场,因为本身“现场”就没有改变)

   ✨代码:

class Solution {
public:
void dfs(vector<vector<int>> &result,int I, int n, int k, vector<int> &lab, set<int> &f)
{
    if (f.size() == k)
    {
        result.push_back(lab);
        return;
    }
    for (int i = I; i <= n; i++)
    {
        if (f.find(i) != f.end())
            continue;
        f.insert(i);
        lab.push_back(i);
        //I=i;
        dfs(result,++I, n, k, lab, f);
        lab.pop_back();
        f.erase(i);
    }
}
vector<vector<int>> combine(int n, int k)
{
    vector<vector<int>> result;
    vector<int> lab;
    set<int> f;
    dfs(result,1, n, k, lab, f);
    return result;
}
};

在这里插入图片描述

 👉⭐️第二题💎

   ✨题目

       image.png

   ✨思路:

深搜其实就是递归,注意这里退出条件需要是判断是否是叶子节点,最好不要是node==nullptr,因为这样会导致当只有一条路径的时候出错,另外需要判断输入[ ]时的输出为false(注意边界),分别找左右子节点进行判断,如果不是Null,则继续往下遍历,否则返回

   ✨代码:

class Solution {
public:
    bool dfs(TreeNode *node, int sum, int targetSum)
    {
        int p = node->val;
        if (node->left == nullptr && node->right == nullptr)
            return sum + p == targetSum ? true : false;
        if (node->left && dfs(node->left, sum + p, targetSum))
            return true;
        if (node->right && dfs(node->right, sum + p, targetSum))
            return true;
        return false;
        }
    bool hasPathSum(TreeNode *root, int targetSum)
    {
        if(root==nullptr)return false;
        return dfs(root, 0,targetSum);
    }
};

在这里插入图片描述

 👉⭐️第三题💎

   ✨题目

       3.太平洋大西洋水流问题
在这里插入图片描述

   ✨思路:

直接想到遍历每一个单元格,模拟以该单元格为起点雨水的流向,将可以同时流进太平洋和大西洋的单元格放进ans中,但这样会多次重复单元格搜索,时间复杂度太高,所以采取反向搜索的方法;即以矩阵边界的单元格为起点,分别寻找雨水可以流经的区域,随后找两大洋的共同区域

   ✨代码:

   int[] X = {0, 0, -1, 1};
    int[] Y = {-1, 1, 0, 0};

    boolean flag1 = false;
    boolean flag2 = false;

    List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        int m = heights.length;
        int n = heights[0].length;
        boolean[][] used = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                flag1 = false;
                flag2 = false;
                dfs(heights,i,j,used);
                if (flag1 && flag2){
                    List<Integer> list = new ArrayList<>();
                    list.add(i);
                    list.add(j);
                    res.add(list);
                }
            }
        }
        return res;
    }

    private void dfs(int[][] heights, int i, int j,boolean[][] used) {
        used[i][j] = true;
        for (int k = 0; k < 4; k++) {
            int x = i + X[k];
            int y = j + Y[k];
            if (x < 0 || y < 0){
                flag1 = true;
            }else if (x >= heights.length || y >= heights[0].length) {
                flag2 = true;
            }else if (!used[x][y] && heights[x][y] <= heights[i][j]){
                dfs(heights,x,y,used);
            }
            if (flag2 && flag1){
                used[i][j] = false;
                return;
            }
        }
        used[i][j] = false;
    }


写在最后
相信大家对今天的集训内容的理解与以往已经有很大不同了吧,或许也感受到了算法的魅力,当然这是一定的,路漫漫其修远兮,吾将上下而求索!伙伴们,明天见!在这里插入图片描述