深搜(DFS)与广搜(BFS):初始问题状态空间

广度遍历:方便最优化问题的求解
leetcode题目实例解析
993. 二叉树的堂兄弟节点
深搜

public:
    int dfs(TreeNode *root,int x,TreeNode *&father){
        if(root==nullptr) return -1;
        if(root->val == x) return 0;
        father = root;
        int l=dfs(root->left,x,father);
        if(l!=-1) return l+1;
        father = root;
        l = dfs(root->right,x,father);
        if(l!=-1) return l+1;
        return -1;
    }
    bool isCousins(TreeNode* root, int x, int y) {
        int d1,d2;
        TreeNode *father_x,*father_y;
        d1 = dfs(root,x,father_x);
        d2 = dfs(root,y,father_y);
        return d1==d2&&father_x!=father_y;
    } 
};

广搜

    //广搜=>相当于层序遍历需要一个辅助的队列
public:
    struct Data{
        Data(TreeNode *node=nullptr,TreeNode *father=nullptr,int deepth=0):node(node),deepth(deepth),father(father){}
        TreeNode *node,*father;
        int deepth;
    };
    bool isCousins(TreeNode* root, int x, int y){
        int d1,d2;
        TreeNode *father_y,*father_x;
        queue<Data> q;
        q.push(Data(root,nullptr,0));
        while(!q.empty()){
            Data cur = q.front();
            if(cur.node->val == x) d1 = cur.deepth,father_x = cur.father;
            if(cur.node->val == y) d2 = cur.deepth,father_y = cur.father;
            if(cur.node->left){
                q.push(Data(cur.node->left,cur.node,cur.deepth+1));
            }
            if(cur.node->right){
                q.push(Data(cur.node->right,cur.node,cur.deepth+1));
            }
            q.pop();            
        }
        
        return d1==d2&&father_x!=father_y;
    }
  1. 01 矩阵
    (使用方向数组进行优化)
class Solution {
public:
    //第一步:状态定义 
    struct Data{
        Data(int i=0,int j=0,int k=0):i(i),j(j),k(k){}
        int i,j,k;//k代表某一个0号节点到当前节点的最短路径,i、j代表所处位置

    };
    void init_queue(queue<Data> &q,vector<vector<int>> &vis,int n,int m,vector<vector<int>>&mat){
        for(int i=0;i<n;i++){
            vis.push_back(vector<int>());
            for(int j =0;j<m;j++){
                vis[i].push_back(-1);
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(mat[i][j]) continue;
                vis[i][j]=0;
                q.push(Data(i,j,0));
            }
        }
        return ;
    }
    int dir[4][2] = {0,1,1,0,0,-1,-1,0};
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
        queue<Data>q;//广搜队列
        vector<vector<int>> vis;//代表某个点是否访问过
        int n = mat.size(),m =mat[0].size();//行数和列数
        init_queue(q,vis,n,m,mat);
        while(!q.empty()){
            Data cur = q.front();//取状态
            for(int k=0;k<4;k++){//扩展状态
                int x = cur.i+dir[k][0];
                int y = cur.j+dir[k][1];
                if(x<0 || x>=n) continue;
                if(y<0 || y>=m) continue;
                if(vis[x][y] !=-1)continue;
                vis[x][y] = cur.k+1;
                q.push(Data(x,y,cur.k+1));
            }
            q.pop();//出状态
        }
        return vis;
    }
};
  1. 二进制矩阵中的最短路径
class Solution {
public:
//定义状态
    struct Data{
        Data(int i=0,int j=0,int l=0):i(i),j(j),l(l){}
        int i,j,l;
    };
    //定义扩展状态
    int dir[8][2]={
        0,1,1,0,0,-1,-1,0,
        1,-1,-1,1,1,1,-1,-1
        };//初始化8个方向
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        int n=grid.size();
        vector<vector<int>> vis;
        for(int i=0;i<n;i++){
            vis.push_back(vector<int>(n));//将vector矩阵初始化为0
        }
        queue<Data> q;
        if(grid[0][0])return -1;
        vis[0][0]=1;
        q.push(Data(0,0,1));
        while(!q.empty()){
            Data cur = q.front();
            if(cur.i == n-1&&cur.j == n-1) return cur.l;
            for(int k = 0;k<8;k++){
                int x = cur.i+dir[k][0];
                int y = cur.j+dir[k][1];
                //排除非法状态
                if(x<0 ||x>=n)continue;
                if(y<0 ||y>=n)continue;
                if(grid[x][y]) continue;
                if(vis[x][y]) continue;//如果经历过就跳过
                vis[x][y] = 1;
                q.push(Data(x,y,cur.l+1));
            }
            q.pop();
        }
        return -1;
    }
};

剑指 Offer 13. 机器人的运动范围

class Solution {
public:
    struct Data{
        Data(int i=0,int j=0):i(i),j(j){}
        int i,j;//当前下标
    };
    int dir[4][2]={0,1,1,0,0,-1,-1,0};
    int movingCount(int m, int n, int k) {
        vector<int> dsum(100);
        for(int i=0;i<10;i++){
            for(int j=0;j<10;j++){
                dsum[i*10+j] = i+j;
            }
        }
        queue<Data> q;
        unordered_set<int> h;
        h.insert(0);
        q.push(Data(0,0));
        int ans = 0;
        while(!q.empty()){
            Data cur = q.front();
            ans+=1;
            //扩展状态
            //通过偏移量到达新点的坐标
            for(int i=0;i<4;i++){
                int x = cur.i+dir[i][0];
                int y = cur.j+dir[i][1];
                if(x<0 || x>=m) continue;
                if(y<0 || y>=n) continue;
                if(h.find(x*n+y)!= h.end()) continue;
                if(dsum[x]+dsum[y]>k) continue;
                h.insert(x*n+y);
                q.push(Data(x,y));

            }
            q.pop();
        }
        return ans;
    }
};
  1. 被围绕的区域
class Solution {
public:
//深搜加标记
    int n,m;
    int dir[4][2] = {0,1,1,0,0,-1,-1,0};
    void dfs(int i,int j,vector<vector<char>>&board){
        board[i][j] ='o';
        //遍历问题求解树的每条边
        for(int k=0;k<4;k++){
            int x =i+dir[k][0];
            int y =j+dir[k][1];
            if(x<0 || x>=n)continue ;
            if(y<0 || y>=m)continue ;
            if(board[x][y]!='O')continue;
            dfs(x,y,board);

        }
        return ;
    }
    void solve(vector<vector<char>>& board) {
        n = board.size() , m=board[0].size();
        for(int i=0;i<n;i++){
            if(board[i][0] =='O')dfs(i,0,board);
            if(board[i][m-1]=='O')dfs(i,m-1,board);
        }
        for(int j=0;j<m;j++){
                if(board[0][j]=='O')dfs(0,j,board);
                if(board[n-1][j] =='O')dfs(n-1,j,board);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(board[i][j]=='O')board[i][j] = 'X';
                else if(board[i][j]=='o')board[i][j] = 'O';
            }
        }
        return ;
    }
}; 
  1. 目标和
class Solution {
public:
    // int dfs(int i,int target,vector<int>&nums){
    //     if(i == nums.size()){
    //         return target == 0;
    //     }
    //     int ans = 0;
    //     ans += dfs(i+1,target-nums[i],nums);//+
    //     ans += dfs(i+1,target+nums[i],nums);//-
    //     return ans ;
    // }
    
    //记忆化
    typedef pair<int,int> PII;
    struct CMP{
        int operator()(const PII &a) const{
            return a.first ^ a.second;
        }
    };
    unordered_map<PII,int,CMP> h;
    int dfs(int i,int target,vector<int>&nums){
        if(i == nums.size()) return target == 0;
        if(h.find(PII(i,target))!=h.end())
            return h[PII(i,target)];
        int ans = 0;
        ans += dfs(i+1,target-nums[i],nums);//+
        ans += dfs(i+1,target+nums[i],nums);//-
        h[PII(i,target)] =ans;
        return ans ;
    }
    int findTargetSumWays(vector<int>& nums, int target) {
        return dfs(0,target,nums);
    }
};
  1. 火柴拼正方形
class Solution {
public:
    bool dfs(int ind,vector<int>&arr,vector<int>&ms){ //i表示第几根木棍 ,arr表示剩余的四个桶的剩余容量,ms表示木棍数目
    if(ind==-1) return -1;
    for(int i=0;i<4;i++){
        if(arr[i] < ms[ind])continue;
        if(arr[i] == ms[ind]||arr[i]>=ms[ind]+ms[0]) {
            arr[i] -= ms[ind];
            if(dfs(ind-1,arr,ms)) return true;//说明能继续往下搜索
            arr[i] += ms[ind];
            }
        }
        return false; 
    }
    bool makesquare(vector<int>& matchsticks) {
        //先对木棍数进行排序然后到这进行搜索(大的先放入桶中)
        sort(matchsticks.begin(),matchsticks.end());
        vector<int> arr(4);//定义了4个桶容量
        int sum = 0; 
        for(auto x:matchsticks) sum += x;
        if(sum%4)return false;
        for(int i=0;i<4;i++)arr[i] = sum/4;//四个桶的剩余容量
        return dfs(matchsticks.size()-1,arr,matchsticks);
    }
};
  1. 组合总和
class Solution {
public:
    void dfs(int ind,int target,vector<int>&nums,vector<int>& buff,vector<vector<int>>&ret){
        if(target < 0) return ;
        if(target==0){
            ret.push_back(buff);
            return ;    
        }
        if(ind == nums.size()) return;
        dfs(ind+1,target,nums,buff,ret);
        buff.push_back(nums[ind]);
        dfs(ind,target-nums[ind],nums,buff,ret);
        buff.pop_back();
        return ; 
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> buff;
        vector<vector<int>> ret;
        dfs(0,target,candidates,buff,ret);
        return ret;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值