• 数据结构刷题——dfs


    一、kotori和素因子

    kotori拿到了一些正整数。她决定从每个正整数取出一个素因子。但是,kotori有强迫症,她不允许两个不同的正整数取出相同的素因子。

    她想知道,最终所有取出的数的和的最小值是多少?

    注:若 a mod k==0,则称 k 是 a 的因子。若一个数有且仅有两个因子,则称其是素数。显然1只有一个因子,不是素数。

    思路:将每个数的质因子求出来,然后进行dfs找寻答案,不用考虑最小是因为根据题意找出来必然就是最小答案。

    #include 
    using namespace std;
    
    int n;
    int a[1010];//正整数的值
    int mi=1e9;
    //判断是否为质数
    bool primer(int x){
       for(int i=2;i*i<=x;i++){
           if(x%i==0){
               return false;
           }
       }
        return true;
    }
    void dfs(int x,set<int> s,int temp){
        if(x==n){
            mi=min(mi,temp);
            return;
        }
        for(int i=2;i<=a[x];i++){
            if(a[x]%i==0 && primer(i)&&!s.count(i)){
                s.insert(i);
                dfs(x+1,s,temp+i);
                s.erase(i);
            }
        }
    }
    int  main(){
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        set<int> s;
        dfs(0,s,0);
        if(mi==1e9)cout<<-1;
        else cout<<mi;
        return 0;
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    二、岛屿数量

    解法一:dfs

    矩阵中多处聚集着1,要想统计1聚集的堆数而不重复统计,那我们可以考虑每次找到一堆相邻的1,就将其全部改成0,而将所有相邻的1改成0的步骤又可以使用深度优先搜索(dfs):当我们遇到矩阵的某个元素为1时,首先将其置为了0,然后查看与它相邻的上下左右四个方向,如果这四个方向任意相邻元素为1,则进入该元素,进入该元素之后我们发现又回到了刚刚的子问题,又是把这一片相邻区域的1全部置为0,因此可以用递归实现。

    • 优先判断空矩阵等情况。
    • 从上到下从左到右遍历矩阵每一个位置的元素,如果该元素值为1,统计岛屿数量。
    • 接着将该位置的1改为0,然后使用dfs判断四个方向是否为1,分别进入4个分支继续修改。
    class Solution {
    public:
        //深度优先遍历与i,j相邻的所有1
        void dfs(vector<vector<char>>& grid, int i, int j) { 
            int n = grid.size();
            int m = grid[0].size();
            //置为0
            grid[i][j] = '0'; 
            //后续四个方向遍历
            if(i - 1 >= 0 && grid[i - 1][j] == '1') 
                dfs(grid, i - 1, j);
            if(i + 1 < n && grid[i + 1][j] == '1') 
                dfs(grid, i + 1,j);
            if(j - 1 >= 0 && grid[i][j - 1] == '1') 
                dfs(grid, i, j - 1);
            if(j + 1 < m && grid[i][j + 1] == '1') 
                dfs(grid, i, j + 1);
        }
        int solve(vector<vector<char> >& grid) {
            int n = grid.size();
            //空矩阵的情况
            if (n == 0)  
                return 0;
            int m = grid[0].size();
            //记录岛屿数
            int count = 0; 
            //遍历矩阵
            for(int i = 0; i < n; i++){ 
                for(int j = 0; j < m; j++){
                    //遍历到1的情况
                    if(grid[i][j] == '1'){ 
                        //计数
                        count++; 
                        //将与这个1相邻的所有1置为0
                        dfs(grid, i, j); 
                    }
                }
            }
            return count;
        }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    时间复杂度:O(nm),其中m、n为矩阵的长和宽,需要遍历整个矩阵,每次dfs搜索需要经过每个值为1的元素,但是最坏情况下也只是将整个矩阵变成0,因此相当于最坏遍历矩阵2次
    空间复杂度:O(nm),最坏情况下整个矩阵都是1,递归栈深度为mn

    解法二:bfs

    • 优先判断空矩阵等情况。
    • 从上到下从左到右遍历矩阵每一个位置的元素,如果该元素值为1,统计岛屿数量。
    • 使用bfs将遍历矩阵遇到的1以及相邻的1全部置为0:利用两个队列辅助(C++可以使用pair),每次队列进入第一个进入的1,然后遍历队列,依次探讨队首的四个方向,是否符合,如果符合则置为0,且位置坐标加入队列,继续遍历,直到队列为空。
    class Solution {
    public:
        int solve(vector<vector<char> >& grid) {
            int n = grid.size();
            //空矩阵的情况
            if(n == 0)   
                return 0;
            int m = grid[0].size();
            //记录岛屿数
            int count = 0; 
            //遍历矩阵
            for(int i = 0; i < n; i++){ 
                for(int j = 0; j < m; j++){
                    //遇到1要将这个1及与其相邻的1都置为0
                    if(grid[i][j] == '1'){  
                        //岛屿数增加
                        count++; 
                        grid[i][j] = '0';
                        //记录后续bfs的坐标
                        queue<pair<int, int>> q; 
                        q.push({i, j}); 
                        //bfs
                        while(!q.empty()){ 
                            auto temp = q.front();
                            q.pop();
                            int row = temp.first;
                            int col = temp.second;
                            //四个方向依次检查:不越界且为1
                            if(row - 1 >= 0 && grid[row - 1][col] == '1'){
                                q.push({row - 1, col});
                                grid[row - 1][col] = '0';
                            }
                            if(row + 1 < n && grid[row + 1][col] == '1'){
                                q.push({row + 1, col});
                                grid[row + 1][col] = '0';
                            }
                            if(col - 1 >= 0 && grid[row][col - 1] == '1'){
                                q.push({row, col - 1});
                                grid[row][col - 1] = '0';
                            }
                            if(col + 1 < m && grid[row][col + 1] == '1'){
                                q.push({row, col + 1});
                                grid[row][col + 1] = '0';
                            }
                        }
                    }
                }
            }
            return count;
        }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    时间复杂度:O(nm),其中m、n为矩阵的长和宽,需要遍历整个矩阵,每次bfs搜索需要经过每个值为1的元素,但是最坏情况下也只是将整个矩阵变成0,因此相当于最坏遍历矩阵2次
    空间复杂度:(min(n,m)),bfs最坏情况队列大小为长和宽的较小值

  • 相关阅读:
    子网计算:192.168.0.0/16是什么意思
    react路由传参的几种方式
    智能指针基础知识【C++】【RAII思想 || unique_ptr || shared_ptr&weak_ptr || 循环引用问题】
    TI DSP的中断
    【深度优先搜索】leetcode 1020. 飞地的数量
    Linux/Ubuntu/Arm设备中通过/proc/stat等文件计算Cpu使用率
    Unable to correct problems, you have held broken packages
    1.renren框架windows下搭建
    动态规划算法(3)(不同方案数问题+拆分问题)
    MySQL-笔记-07.试图及索引的应用
  • 原文地址:https://blog.csdn.net/qwer1234mnbv_/article/details/126077492