递归搜索与回溯的算法设计与例题

一.递归

1.汉诺塔问题

面试题 08.06. 汉诺塔问题 - 力扣(LeetCode)

class Solution 
{
public:
    void dfs(vector<int>& a, vector<int>& b, vector<int>& c,int n) //把a经过b传到c上,传n个盘子
    {
        if(n==1)  //出口    
        {
            c.push_back(a.back());
            a.pop_back();
            return;
        }

        dfs(a,c,b,n-1);
        c.push_back(a.back());
        a.pop_back();
        dfs(b,a,c,n-1);
    }
    void hanota(vector<int>& a, vector<int>& b, vector<int>& c) 
    {
        dfs(a,b,c,a.size());    
    }
};

2.合并两个有序链表

21. 合并两个有序链表 - 力扣(LeetCode)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution 
{
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)  //函数的功能是连接两个节点并返回
    {
        if(l1==nullptr) return l2;
        if(l2==nullptr) return l1;

        if(l1->val <= l2->val) 
        {
            l1->next=mergeTwoLists(l1->next,l2);
            return l1;
        }
        else
        {
            l2->next=mergeTwoLists(l1,l2->next);
            return l2;
        }
    }
};

3.反转链表

206. 反转链表 - 力扣(LeetCode)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution 
{
public:
    ListNode* reverseList(ListNode* head) 
    {
        if(head==nullptr || head->next==nullptr) return head;

        ListNode* newhead=reverseList(head->next);
        head->next->next=head;
        head->next=nullptr;
        return newhead;    //相当于后序遍历,而且newhead指向最后一个往前递归的时候就再也没变过
    }
};

4.两两交换链表中的结点

24. 两两交换链表中的节点 - 力扣(LeetCode)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution 
{
public:
    ListNode* swapPairs(ListNode* head) 
    {
        if(head==nullptr || head->next==nullptr) return head;

        ListNode* tmp=swapPairs(head->next->next);
        ListNode* next=head->next;
        if(next==nullptr) return head;
        next->next=head;
        head->next=tmp;
        return next;
    }
};

5.Pow(x,n) - 快速幂

50. Pow(x, n) - 力扣(LeetCode)

class Solution 
{
public:
    double myPow(double x, int n) 
    {
        if(n==0) return 1;

        if(n==INT_MIN)
        {
            return  1/(myPow(x,INT_MAX)*x*1.0);
        }
        if(n<0) 
        {
            n=n*(-1);
            double tmp=myPow(x,n/2);
            if(n%2==0) return 1/(tmp*tmp*1.0);
            else return 1/(tmp*tmp*x*1.0);
        }
    
        double tmp=myPow(x,n/2);
        if(n%2==0) return tmp*tmp;
        else return tmp*tmp*x;
    }
};

二.二叉树中的深搜

1.计算布尔二叉树的值

2331. 计算布尔二叉树的值 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution 
{
public:
    bool evaluateTree(TreeNode* root) 
    {
        if(root->val==0) return false;
        if(root->val==1) return true;

        bool left=evaluateTree(root->left);
        bool right=evaluateTree(root->right);
        if(root->val==2) return (left || right);
        if(root->val==3) return (left && right);
        return true;
    }
};

2.求根节点到叶节点数字之和

129. 求根节点到叶节点数字之和 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution 
{
public:
    int dfs(TreeNode* root,int prevsum)
    {
        prevsum=prevsum*10+root->val;
        if(root->left==nullptr && root->right==nullptr) return prevsum;
        int sum=0;
        if(root->left) sum += dfs(root->left,prevsum);
        if(root->right) sum += dfs(root->right,prevsum);
        return sum;
    }

    int sumNumbers(TreeNode* root) 
    {
        return dfs(root,0);
    }
};

 3.二叉树剪

814. 二叉树剪枝 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution 
{
public:
    TreeNode* pruneTree(TreeNode* root) 
    {
        if(root==nullptr) return nullptr;

        root->left=pruneTree(root->left);
        root->right=pruneTree(root->right);

        if(root->val==0 && root->left==nullptr && root->right==nullptr) 
        {
            delete root;
            root=nullptr;
        }
        return root;
    }
};

4.验证二叉搜索树

98. 验证二叉搜索树 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */

class Solution 
{
public:
    long prev=LONG_MIN;  //int不够小
    bool isValidBST(TreeNode* root) 
    {   
        if(root==nullptr) return true;

        bool left=isValidBST(root->left);
        if(left==false) return false;      //剪枝1

        bool cur=false;
        if((root->val)>prev) cur=true;    
        if(cur==false) return false;       //剪枝2

        
        prev=root->val;                   
        bool right=isValidBST(root->right);
        return left&&right&&cur;  
    }
};

5.二叉搜索树中第k小的元素

230. 二叉搜索树中第K小的元素 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution 
{
    int Min=INT_MAX;
    int count=0;

public:
    void dfs(TreeNode* root, int k)
    {
        if(root==nullptr) return ;

        dfs(root->left,k);
        if(count<k)
        {
            Min=root->val;
            count++;
        }
        else return;
        dfs(root->right,k);
    }
    int kthSmallest(TreeNode* root, int k) 
    {
        dfs(root,k);
        return Min;
    }
};

6.二叉树的所有路径

257. 二叉树的所有路径 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution 
{
public:
    vector<string> ans;
    void dfs(TreeNode* root,string path)
    {
        if(root==nullptr) return ;

        path += to_string(root->val); 
        if(root->left==nullptr && root->right==nullptr)  //是叶子节点
        {           
            ans.push_back(path);
            return;
        }
        else
        {
            path += "->";
        }
        dfs(root->left,path);
        dfs(root->right,path);
        return;
    }

    vector<string> binaryTreePaths(TreeNode* root) 
    {
        string path;
        dfs(root,path);
        return ans;
    }
};

三.穷举vs暴搜vs深搜vs回溯vs剪枝

1.全排列

46. 全排列 - 力扣(LeetCode)

class Solution 
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    bool check[10];
    void dfs(vector<int>& nums)
    {
        if(path.size()==nums.size())  //递归出口
        {
            ret.push_back(path);
            return ;
        }

        for(int i=0;i<nums.size();i++)
        {
            if(check[i]==false)
            {
                path.push_back(nums[i]);
                check[i]=true;
                dfs(nums);
                //递归完之后回溯(恢复现场)
                path.pop_back();
                check[i]=false;
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) 
    {
        dfs(nums);
        return ret;
    }
};

2.子集

78. 子集 - 力扣(LeetCode)

方法一:
class Solution 
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    
    vector<vector<int>> subsets(vector<int>& nums) 
    {
        dfs(nums,0);
        return ret;
    }
    void dfs(vector<int> nums,int pos)
    {
        if(pos==nums.size())
        {
            ret.push_back(path);
            return;
        }

        //选
        path.push_back(nums[pos]);
        dfs(nums,pos+1);
        path.pop_back();   //选完之后要恢复现场

        //不选
        dfs(nums,pos+1);
    }
};

 

方法二:
class Solution 
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    
    vector<vector<int>> subsets(vector<int>& nums) 
    {
        dfs(nums,0);
        return ret;
    }
    void dfs(vector<int> nums,int pos)
    {
        ret.push_back(path);  //方法二你上来就先打进去
        for(int i=pos;i<nums.size();i++)
        {
            path.push_back(nums[i]);
            dfs(nums,i+1);
            path.pop_back();   //回复现场
        }
    }
};

因为是根据决策树按1-n的顺序遍历的,所以不会出现231这种情况

四.综合练习

1.找出所有子集的异或总和再求和

1863. 找出所有子集的异或总和再求和 - 力扣(LeetCode)

class Solution 
{
public:
    int sum=0;
    int path=0;
    int subsetXORSum(vector<int>& nums) 
    {
        dfs(nums,0);
        return sum;
    }
    void dfs(vector<int>& nums,int pos)
    {
        if(nums.size()==pos)
        {
            sum += path;
            return;
        }

        //选
        path ^= nums[pos];
        dfs(nums,pos+1);
        path ^=nums[pos];

        //不选
        dfs(nums,pos+1);
    }
};

2.全排列II

47. 全排列 II - 力扣(LeetCode)

class Solution 
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    bool check[10];
    void dfs(vector<int>& nums)
    {
        if(path.size()==nums.size())
        {
            ret.push_back(path);
            return ;
        }

        for(int i=0;i<nums.size();i++)
        {
            if((check[i]==false)&&(i==0 || nums[i-1]!=nums[i] || check[i-1]==true))  //check[i-1]==true表示在nums[i-1]!=nums[i]的前提下
            {
                path.push_back(nums[i]);
                check[i]=true;
                dfs(nums);
                path.pop_back();
                check[i]=false;
            }
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) 
    {
        sort(nums.begin(),nums.end());   //必须要先排序
        dfs(nums);
        return ret;
    }
};

3.电话号码的字母组合

17. 电话号码的字母组合 - 力扣(LeetCode)

class Solution 
{
public:
    string path;
    vector<string> ret;
    vector<string> hash={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    void dfs(string digits,int pos)
    {
        if(pos==digits.size())
        {
            ret.push_back(path);
            return;
        }

        string tmp=hash[digits[pos]-'0'];
        for(int i=0;i<tmp.size();i++)
        {
                path.push_back(tmp[i]);    //只是需要普通的深度遍历,不需要判断check
                dfs(digits,pos+1);
                path.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) 
    {
        if(digits.size()==0) return ret;
        dfs(digits,0);
        return ret;
    }
};

4.括号生成

22. 括号生成 - 力扣(LeetCode)

class Solution 
{
public:
    int left=0,right=0,n;
    vector<string> ret;
    string path;
    void dfs()
    {
        if(right==n)
        {
            ret.push_back(path);
            return;
        }
        
        if(left<n)   //添加左括号  (剪枝反过来了)
        {
            path.push_back('(');
            left++;
            dfs();   //在返回出回复现场
            left--;
            path.pop_back();
        } 

        if(right<left)  //添加右括号 (剪枝反过来了)
        {
            path.push_back(')');
            right++;
            dfs();
            right--;
            path.pop_back();
        }
    }

    vector<string> generateParenthesis(int m) 
    {
        n=m;
        dfs();
        return ret;
    }
};

5.组合

77. 组合 - 力扣(LeetCode)

class Solution 
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    int count=0;
    int kk=0;
    void dfs(int n,int pos)
    {
        if(count==kk)
        {
            ret.push_back(path);
            return;
        }

        for(int i=pos;i<=n;i++)
        {
            path.push_back(i);
            count++;
            dfs(n,i+1);
            path.pop_back();
            count--;
        }
    }

    vector<vector<int>> combine(int n, int k) 
    {
        kk=k;
        if(k>n) return ret;
        dfs(n,1);
        return ret; 
    }
};

6.目标和

494. 目标和 - 力扣(LeetCode)

class Solution 
{
public:
    int sum=0;
    int target=0;
    int ans=0;
    void dfs(vector<int>& nums,int pos)
    {
        if(pos==nums.size())
        {
            if(sum==target) ans++;
            return;
        }

        //选加
        sum += nums[pos];
        dfs(nums,pos+1);
        sum -= nums[pos];

        //选减
        sum -= nums[pos];
        dfs(nums,pos+1);
        sum += nums[pos];
    }
    int findTargetSumWays(vector<int>& nums, int _target) 
    {
        target=_target;
        dfs(nums,0);
        return ans;
    }
};
sum作为局部变量:可以防止时间超时,而且也不用回复现场
class Solution 
{
public:
    int target=0;
    int ans=0;
    void dfs(vector<int>& nums,int pos,int sum)
    {
        if(pos==nums.size())
        {
            if(sum==target) ans++;
            return;
        }
        //选加
        dfs(nums,pos+1,sum+nums[pos]);

        //选减
        dfs(nums,pos+1,sum-nums[pos]);
    }
    int findTargetSumWays(vector<int>& nums, int _target) 
    {
        target=_target;
        dfs(nums,0,0);
        return ans;
    }
};

7.组合总和

39. 组合总和 - 力扣(LeetCode)

class Solution 
{
public:
    int target=0;
    vector<int> path;
    vector<vector<int>> ret;
    void dfs(vector<int>& nums,int pos,int sum)
    {
        if(sum==target)
        {
            ret.push_back(path);
            return ;
        }
        if((pos==nums.size()) || (sum>target)) return ;
        for(int i=pos;i<nums.size();i++)
        {
            path.push_back(nums[i]);
            dfs(nums,i,sum+nums[i]);
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum(vector<int>& nums, int _target) 
    {
        target=_target;
        dfs(nums,0,0);
        return ret;
    }
};

8.字母大小写全排列

784. 字母大小写全排列 - 力扣(LeetCode)

class Solution 
{
public:
    vector<string> ret;
    string path;

    void dfs(string& s,int pos)
    {   
        if(pos==s.size())
        {
            ret.push_back(path);
            return;
        }

        //不改变
        path.push_back(s[pos]);
        dfs(s,pos+1);
        path.pop_back();

        //改变
        if(s[pos]>'9' || s[pos]<'0')   //字符串中只有字符和数字
        {
            char tmp=change(s[pos]);
            path.push_back(tmp);
            dfs(s,pos+1);
            path.pop_back();       
        }
    }

    char change(char ch)
    {
        if(ch>='a' && ch<='z')  ch -= 32;
        else if(ch>='A' && ch<='Z')  ch += 32;
        return ch;
    }

    vector<string> letterCasePermutation(string s) 
    {
        dfs(s,0);
        return ret;
    }
};

9.优美的排列

526. 优美的排列 - 力扣(LeetCode)

class Solution 
{
public:
    bool check[16];
    int ret;
    void dfs(int pos,int n)
    {
        if(pos==n+1)  //下标填到n,所以递归出口结束是n+1
        {
            ret++;
            return;
        }
        for(int i=1;i<=n;i++)
        {
            if(check[i]==false && (pos%i==0 || i%pos==0))
            {
                check[i]=true;
                dfs(pos+1,n);   //是pos+1,不是i+1 ,只有求子集才用i+1
                //若pos:1->2->3->... 若i: 1->1->1->...再回来
                check[i]=false;
            }
        }
    }

    int countArrangement(int n) 
    {
        dfs(1,n);
        return ret;
    }
};

10.N皇后

51. N 皇后 - 力扣(LeetCode)

class Solution 
{
public:
    bool checkCol[10];
    bool checkDig1[20];  //主对角线
    bool checkDig2[20];  //副对角线
    vector<vector<string>> ret;
    vector<string> path;
    int n;
    void dfs(int pos)   //pos表示正在遍历第几行 (pos表示行)
     {
        if(pos==n)
        {
            ret.push_back(path);
            return ;
        }

        for(int j=0;j<n;j++) //尝试在这一行里放皇后
        {
            if(checkCol[j]==false && checkDig1[j-pos+n]==false && checkDig2[j+pos]==false)
            {
                path[pos][j]='Q';
                checkCol[j]=true;
                checkDig1[j-pos+n]=true;
                checkDig2[j+pos]=true;
                dfs(pos+1);   //进到下一行
                path[pos][j]='.';
                checkCol[j]=false;
                checkDig1[j-pos+n]=false;
                checkDig2[j+pos]=false;
            }
        }

    }
    vector<vector<string>> solveNQueens(int _n) 
    {
        n=_n;
        path.resize(n);
        for(int i=0;i<n;i++) path[i].append(n,'.');   //初始化棋盘
        dfs(0);
        return ret;
    }
};

11.有效的数独

36. 有效的数独 - 力扣(LeetCode)

class Solution 
{
public:
    bool row[9][10];
    bool col[9][10];
    bool grid[3][3][10];
    bool isValidSudoku(vector<vector<char>>& board) 
    {   
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                if(board[i][j]!='.')
                {
                    int num=board[i][j]-'0';
                    if(row[i][num] || col[j][num] || grid[i/3][j/3][num]) return false;

                    row[i][num]=true;
                    col[j][num]=true;
                    grid[i/3][j/3][num]=true;
                }
            }
        }
        return true;
    }
};

12.解数独

37. 解数独 - 力扣(LeetCode)

注意剪枝的重要性

class Solution 
{
public:
    bool row[9][10];
    bool col[9][10];
    bool grid[3][3][10];
    bool dfs(vector<vector<char>>& board)
    {
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                if(board[i][j]=='.')
                {
                    //填数
                    for(int num=1;num<=9;num++)
                    {
                        if(row[i][num]==false && col[j][num]==false && grid[i/3][j/3][num]==false)
                        {
                            board[i][j] = '0'+num;
                            row[i][num] = col[j][num] = grid[i/3][j/3][num]=true;
                            if(dfs(board)==true) return true;  //防止在错误的道路上越走越远,减少消耗(剪枝)
                            
                            board[i][j]='.';   //回复现场
                            row[i][num] = col[j][num] = grid[i/3][j/3][num]=false;
                        }
                    }
                    return false;
                }
            }
        }
        return true;   //填完了
    }
    void solveSudoku(vector<vector<char>>& board) 
    {
        //初始化
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                if(board[i][j]!='.')
                {
                    int num=board[i][j]-'0';
                    row[i][num] = col[j][num] = grid[i/3][j/3][num]=true;
                }
            }
        }
        dfs(board);
    }
};

13.单词搜索

79. 单词搜索 - 力扣(LeetCode)

class Solution 
{
public:
    int m,n;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    bool vis[7][7]={false};

    bool dfs(vector<vector<char>>& board,int i,int j,string& s,int pos)
    {
        if(pos==s.size()) return true;
        
        for(int k=0;k<4;k++)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && vis[x][y]==false && board[x][y]==s[pos])
            {
                vis[x][y]=true;
                if(dfs(board,x,y,s,pos+1)) return true;
                vis[x][y]=false;
            }
        }
        return false;
    }

    bool exist(vector<vector<char>>& board, string word) 
    {
        m=board.size();
        n=board[0].size();
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(board[i][j]==word[0])
                {
                    vis[i][j]=true;
                    if(dfs(board,i,j,word,1)) return true;
                    else vis[i][j]=false;
                }
            }
        }
        return false;
    }
};

14.黄金矿工

1219. 黄金矿工 - 力扣(LeetCode)

class Solution 
{
public:
    int m;
    int n;
    bool vis[16][16]={false};
    int ret=0;
    int maxret=0;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};

    void dfs(vector<vector<int>>& grid,int i,int j)
    {
        maxret=max(maxret,ret);   //有可能自己一个就是最大的
        for(int k=0;k<4;k++)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && vis[x][y]==false && grid[x][y]!=0)
            {
                int tmp=grid[x][y];
                ret += grid[x][y];
                grid[x][y]=0;
                vis[x][y]=true;

                dfs(grid,x,y);

                grid[x][y]=tmp;
                ret -= grid[x][y];
                vis[x][y]=false;  
            }
        }
    }

    int getMaximumGold(vector<vector<int>>& grid) 
    {
        m=grid.size();
        n=grid[0].size();

        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(grid[i][j]!=0)
                {
                    ret = grid[i][j];
                    vis[i][j]=true;
                    dfs(grid,i,j);   //从ij开始dfs时没包括自己,注意把他自己加上,还要注意回复现场与改变vis数组
                    vis[i][j]=false;
                } 
            }
        }
        return maxret;
    }
};

15.不同路径III

980. 不同路径 III - 力扣(LeetCode)

class Solution 
{
public:
    int count=1;   //起点自己本身占一个格子
    int ret=0;
    int m,n;
    int sum;   //0的格子个数
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    bool vis[20][20];
    void dfs(vector<vector<int>>& grid,int i,int j)
    {
        if(grid[i][j]==2)  //走到终点了
        {
            if(count==sum) ret++;
            return;
        }
        
        for(int k=0;k<4;k++)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && vis[x][y]==false && grid[x][y]!=-1)  //只要不等于-1就行
            {
                count++;
                vis[x][y]=true;
                dfs(grid,x,y);
                count--;
                vis[x][y]=false;
            }
        }

    }

    int uniquePathsIII(vector<vector<int>>& grid) 
    {
        m=grid.size();
        n=grid[0].size();
        int beginx,beginy;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(grid[i][j]==0) sum++;
                else if(grid[i][j]==1)
                {
                    beginx=i;
                    beginy=j;
                }
            }
        } 
        sum += 2;  //还要算上起点和终点
        vis[beginx][beginy]=true;
        dfs(grid,beginx,beginy);
        return ret;
    }
};

五.记忆化搜索(递归中的dp)

1.斐波那契数

980. 不同路径 III - 力扣(LeetCode)

class Solution 
{
public:
    int memo[31];   //备忘录
    int dfs(int n)
    {
        //3.每次进入都先往备忘录里查找一下
        if(memo[n] != -1)
        {
            return memo[n];
        }

        if(n==1 || n==0)
        {
            memo[n]=n;  //2.返回之前把值存到备忘录里面
            return memo[n];  //然后仅需返回备忘录的值
        }

        memo[n]=dfs(n-1)+dfs(n-2); //2.返回之前把值存到备忘录里面
        return memo[n];  //然后仅需返回备忘录的值
    }

    int fib(int n) 
    {
        //1.初始化备忘录
        memset(memo,-1,sizeof(memo));
        return dfs(n);
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

对玛导至昏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值