力扣K神图解算法数据结构解析04

力扣K神图解算法数据结构点这里

四、搜索与回溯算法

  1. DFS,本质是递归

    • 递推参数
    • 终止条件
    • 递推工作
    • 回溯
  2. BFS,本质是队列

    queue<int> que;
    que.push(第一个参数);
    
    while(!que.empty())
    {	
        auto tmp = que.front();
        que.pop();
        if(终止条件) continue;
        //进行递推工作
    	que.push(新的参数);
    }
    
  3. 树的递归调用

    • 某函数既然可以递归调用root,那么也一定可以调用root->left和root->right,有时候只需要把任务分解成三部分即可,root节点,递归调用root->left,递归调用root->right
    • 树的遍历方式总体分为两类,DFS和BFS
      1. DFS,前序,中序,后序,其中中序是递增序列
      2. BFS,层序
  4. 剑指12,矩阵中的路径

    //时间O(mn3^k),空间O(k)
    //标准dfs+剪枝,值得学习
    class Solution {
    public:
        bool exist(vector<vector<char>>& board, string word) 
        {
            //每个位置都要作为起点尝试一次
            for(int i=0;i<board.size();++i)
            {
                for(int j=0;j<board[0].size();++j)
                {
                    if(dfs(i,j,0,board,word)) return true;
                }
            }
            return false;
        }
    
    private:
     
        bool dfs(int i,int j,int k,vector<vector<char>>& board, string &word)
        {
            //如果越界或者字符不匹配
            if(i < 0 || i >= board.size() || j < 0 || j >= board[0].size() 
            || board[i][j] != word[k]) return false;
            //执行到这步默认字符匹配,且是最后一个字符
            if(k == word.size()-1) return true;
            //递推工作,修改值
            board[i][j] = '\0';
            //如果有一条路径成功就返回
            auto res = dfs(i,j+1,k+1,board,word) || dfs(i,j-1,k+1,board,word) || 
                       dfs(i+1,j,k+1,board,word) || dfs(i-1,j,k+1,board,word);
            //回溯,恢复原状
            board[i][j] = word[k];
            //返回,很重要
            return res;
        }
    };
    
  5. 剑指13,机器人的运动范围

    //时间O(mn),空间O(mn)
    //标准dfs+剪枝,使用二维数组记录已访问过的位置
    //注意,从左上到右下,只需关注右和下两个方向
    class Solution {
    public:
        int movingCount(int m, int n, int k) 
        {   
            vector<vector<int>> vec(m,vector<int>(n));
            return dfs(m,n,k,0,0,vec);
        }
    
    private:
        int dfs(int m, int n, int k,int i, int j, vector<vector<int>> &vec)
        {   
            //如果越界,数位之和大于k,已访问过
            if(i >= m || j >= n || digitSum(i)+digitSum(j) > k || vec[i][j]) return 0;
            //标记
            vec[i][j] = 1;
            //递推
            return 1 + dfs(m,n,k,i,j+1,vec) + dfs(m,n,k,i+1,j,vec);
        }
        //数位之和
        int digitSum(int num)
        {
            int res = 0;
            int x;
            while(num)
            {
                x = num % 10;
                num /= 10;
                res += x;
            }
            return res;
        }
    };
    
    
    //时间O(mn),空间O(mn)
    //标准bfs+剪枝,使用二维数组记录已访问过的位置
    //熟记bfs套路
    class Solution {
    public:
        int movingCount(int m, int n, int k) 
        {
            queue<pair<int,int>> que;
            que.push({0,0});
            int res = 0;
            vector<vector<int>> vec(m,vector<int>(n));
    
            while(!que.empty())
            {
                auto temp = que.front();
                que.pop();
                if(temp.first >= m || temp.second >= n || 							 			digitSum(temp.first)+digitSum(temp.second) > k ||
                vec[temp.first][temp.second]) continue;
                ++res;
                vec[temp.first][temp.second] = 1;
                que.push({temp.first,temp.second+1});
                que.push({temp.first+1,temp.second});
            }
            return res;
        }
        
    private:
    	//数位之和
        int digitSum(int 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值