zoukankan      html  css  js  c++  java
  • dfs-入门模板

    模板

    void dfs()//参数用来表示状态  
    {  
        if(到达终点状态)  
        {  
            ...//根据题意添加  
            return;  
        }  
        if(越界或者是不合法状态)  
            return;  
        if(特殊状态)//剪枝
            return ;
        for(扩展方式)  
        {  
            if(扩展方式所达到状态合法)  
            {  
                修改操作;//根据题意来添加  
                标记;  
                dfs();  
                (还原标记);  
                //是否还原标记根据题意  
                //如果加上(还原标记)就是 回溯法  
            }  
        }  
    } 

    46. 全排列

    class Solution {
    public:
        vector<vector<int>> res;
        vector<int> vis;
        vector<vector<int>> permute(vector<int>& nums) {
            vector<int> path;
            vis.resize(nums.size(), 0);
            dfs(nums, path, 0);
            return res;
        }
        void dfs(vector<int> & nums, vector<int>& path, int len){//参数表示状态
            if(len == nums.size()){//递归出口
                res.push_back(path);return;
            }
            for(int i = 0;i < nums.size(); i++){//扩展方式
                if(vis[i] == 0){//扩展方式合法
                    path.push_back(nums[i]);
                    vis[i] = 1;
                    dfs(nums,path,len + 1);
                    vis[i] = 0;
                    path.pop_back();
                }
            } 
        }
    };

    47. 全排列 II 排序去重

    class Solution {
    public:
        vector<vector<int>> res;
        vector<int> vis;
        vector<vector<int>> permuteUnique(vector<int>& nums) {
            sort(nums.begin(),nums.end());
            vis.resize(nums.size(),0);
            vector<int> path;
            dfs(nums,path, 0); 
            return res;
        }
        void dfs(vector<int>& nums, vector<int>& path, int depth){
            if(depth == nums.size()){//递归出口
                res.push_back(path);
                return;
            }
            for(int i = 0; i < nums.size(); i++){
                //在同一深度只会遍历第一个相同的数字,不同深度时vis[i-1] = 1
                if(i && nums[i] == nums[i-1] && vis[i-1] == 0) continue;
                if(vis[i] == 0){
                    vis[i] = 1;
                    path.push_back(nums[i]);
                    dfs(nums,path,depth + 1);
                    vis[i] = 0;
                    path.pop_back();
                }
            }
        }
    };

    491. 递增子序列 

    class Solution {
    public:
        vector<vector<int>> res;
        vector<int> vis;
        vector<vector<int>> findSubsequences(vector<int>& nums) {
                vis.resize(nums.size(),0);
               vector<int> path;
               dfs(nums,path,0);
               return res;
        }
        void dfs(vector<int> & nums, vector<int>& path, int start){//参数表示状态,从前往后,depth改为start
            if(path.size() >= 2){//过程状态也要记录
                    res.push_back(path);
            }   
            if(start == nums.size()) return; 
            unordered_set<int> mp;//去重   
            for(int i = start;i < nums.size(); i++){//扩展方式
                //if(vis[i] == 0){这里不需要vis
                if((path.size() == 0 || nums[i] >= path.back()) && mp.count(nums[i]) == 0){
                    mp.insert(nums[i]);
                    path.push_back(nums[i]);
                    dfs(nums,path,i + 1);//这里别写错了
                    path.pop_back();
                }
            } 
        }
    };

    39. 组合总和 

    元素可以重复利用且没有顺序,所以不要vis数组

    class Solution {
    public:
        vector<vector<int>> res;
        vector<vector<int>> combinationSum(vector<int>& nums, int target) {
            vector<int> path;
            dfs(nums,path,0,target);
            return res;
        }
        void dfs(vector<int> &nums,vector<int>& path, int start, int target){
                //出口  
            if(target < 0) return;
            if(target == 0){
                res.push_back(path);
                return;
            }
            //遍历
            for(int i = start; i <nums.size(); i++){
                path.push_back(nums[i]);
                dfs(nums,path,i, target - nums[i]);
                path.pop_back();
            }
        }
    };

    40. 组合总和 II 比上题多了一个去重操作;

    class Solution {
    public:
        vector<vector<int>> res;
        vector<vector<int>> combinationSum2(vector<int>& nums, int target) {
            sort(nums.begin(),nums.end());//加个去重操作
            vector<int> path;
            dfs(nums,path,0,target);
            return res;
        }
        void dfs(vector<int> &nums,vector<int>& path, int start, int target){
                //出口  
            if(target < 0) return;
            if(target == 0){
                res.push_back(path);
                return;
            }
            //遍历
            for(int i = start; i <nums.size(); i++){
                if(i > start && nums[i] == nums[i-1] ) continue;//注意是i > start
                path.push_back(nums[i]);
                dfs(nums,path,i+1, target - nums[i]); // start = i + 1
                path.pop_back();
            }
        }
    };

    78. 子集

    class Solution {
    public:
        vector<vector<int>> res;
        vector<int> vis;
        vector<vector<int>> subsets(vector<int>& nums) {
                vis.resize(nums.size(),0);
               vector<int> path;
               dfs(nums,path,0);
               return res;
        }
        void dfs(vector<int> & nums, vector<int>& path, int start){//参数表示状态,从前往后,depth改为start
             res.push_back(path);   
            if(start == nums.size()) return;    
            for(int i = start;i < nums.size(); i++){//扩展方式
                    //似乎没条件
                    path.push_back(nums[i]);
                    dfs(nums,path,i + 1);//这里别写错了
                    path.pop_back();
            } 
        }
    };

    90. 子集 II 上题基础上加个去重

    class Solution {
    public:
        vector<vector<int>> res;
        vector<int> vis;
        vector<vector<int>> subsetsWithDup(vector<int>& nums) {
                sort(nums.begin(), nums.end());//排序便于去重
                vis.resize(nums.size(),0);
               vector<int> path;
               dfs(nums,path,0);
               return res;
        }
        void dfs(vector<int> & nums, vector<int>& path, int start){//参数表示状态,从前往后,depth改为start
             res.push_back(path);   
            if(start == nums.size()) return;    
            for(int i = start;i < nums.size(); i++){//扩展方式
                    if(i > start && nums[i] == nums[i-1]) continue; //去重
                    path.push_back(nums[i]);
                    dfs(nums,path,i + 1);//这里别写错了
                    path.pop_back();
            } 
        }
    };

    进阶:N皇后问题

    51. N皇后

    class Solution {
    public:
        vector<vector<string>> res;
        vector<vector<string>> solveNQueens(int n) {     
            string t = "";
            for(int i = 0; i < n; i++) t += '.';
            vector<string> path(n,t);
            vector<vector<int>> vis(n, vector<int>(n,0));
            dfs(path,vis,n,0);
            return res;
        }
        void dfs(vector<string>& path,vector<vector<int>> &vis, int& n, int row){
            if(row == n){//递归出口,前n行全部被赋值
                res.push_back(path);return;
            }
            for(int j = 0; j < n; j++){//遍历一行
                if(vis[row][j] == 0){//条件
                    path[row][j] = 'Q';
                    //注意,不能直接让vis变1和变0,否则后来的修改可能会改变原来的修改
                    for(int i = row; i < n; i++)vis[i][j]++;//该列
                    for(int i = row; i < n; i++){//对角线
                        if(j + i - row < n) vis[i][j + i - row]++;
                        if(j + row - i >= 0) vis[i][j + row - i]++;
                    } 
                    dfs(path, vis, n, row + 1);
                    path[row][j] = '.';
                    for(int i = row; i < n; i++)vis[i][j]--;//该列
                    for(int i = row; i < n; i++){//对角线
                        if(j + i - row < n) vis[i][j + i - row]--;
                        if(j + row - i >= 0) vis[i][j + row - i]--;
                    } 
                }
            }
        }
    };

    37. 解数独

    class Solution {
    public:
        int col[9][9] = {0};
        int row[9][9] = {0};
        int box[9][9] = {0};
        void solveSudoku(vector<vector<char>>& board) {
            int n = board.size();
            //初始化
            for(int i = 0; i <9; i++)
                for(int j = 0; j < 9; j++){
                    if(board[i][j] != '.'){
                        int t = board[i][j] - '1';
                        col[j][t]++;
                        row[i][t]++;
                        box[i/3*3+ j/3][t]++;
                    }
                }
            dfs(board, 0, 0);
        }
        //传参 int a[][9] 或者 int (*a)[9] 而不是 (int*)[9] a
        // box x/3*3 + y/3 而不是 x/3 + y/3;
        // (y + 1)%3 而不是 (++y)/3
        bool dfs(vector<vector<char>>& board,  int x, int y){
            if(x == 9) return true;//递归出口
            //特殊状态
            if(board[x][y] != '.') return dfs(board,x + (y==8),(++y)%9);
            for(int k = 0; k < 9; k++){//遍历
                //条件
                if(row[x][k] || col[y][k] || box[x/3*3 + y/3][k]) continue;
                board[x][y]  = k + '1';
                row[x][k]++;col[y][k]++;box[x/3*3 + y/3][k]++;
                if(dfs(board,x + (y==8),(y + 1)%9)) return true;//找到一个解就退出
                board[x][y]  = '.';
                row[x][k]--;col[y][k]--;box[x/3*3 + y/3][k]--;
            }
            return false;
        }
    };
  • 相关阅读:
    Single Number II
    Pascal's Triangle
    Remove Duplicates from Sorted Array
    Populating Next Right Pointers in Each Node
    Minimum Depth of Binary Tree
    Unique Paths
    Sort Colors
    Swap Nodes in Pairs
    Merge Two Sorted Lists
    Climbing Stairs
  • 原文地址:https://www.cnblogs.com/Aliencxl/p/13207730.html
Copyright © 2011-2022 走看看