当前位置:   article > 正文

Leetcode 热题100 回溯_(sum(no_exist{}) or vector(0))

(sum(no_exist{}) or vector(0))

Leetcode 热题100 回溯

<按出题频率排列>

大佬回溯算法详解:

回溯算法入门级详解 + 练习(持续更新) - 全排列 - 力扣(LeetCode) (leetcode-cn.com)

22. 括号生成

解题思路:

如下

/*
递归每一种字符串加入即可
左右括号数量至少有一个不为0,这种情况下只有左括号能为0,右括号必不可能为0,因为最后一个括号一定是右括号
*/
class Solution {
public:
    void addParenthesis(vector<string>& coll, string s, int l, int r){
        if(l == 0 && r == 0){
            coll.push_back(s);
            return;
        }
        if(l == 0){
            addParenthesis(coll, s + ")", l, r - 1);
        }
        else if(l < r){
            addParenthesis(coll, s + "(", l - 1, r);
            addParenthesis(coll, s + ")", l, r - 1);
        }
        else if(l == r){
            addParenthesis(coll, s + "(", l - 1, r);
        }
    }
    vector<string> generateParenthesis(int n) {
        string s;
        vector<string> res;
        addParenthesis(res, s, n, n);
        return res;
    }
};
  • 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

46. 全排列

解题思路:

见顶部回溯算法详解

class Solution {
public:
    //depth表示树的总深度,idex表示当前深度
    void dfs(vector<vector<int>> &res, vector<int> &used, vector<int> &nums, vector<int> &s, int &depth, int idex){
        if(depth < idex) res.push_back(s);
        for(int i = 0; i < depth; i++){
            if(used[i] == 0){
                s.push_back(nums[i]);
                used[i] = 1;//标记已经使用
                dfs(res, used, nums, s, depth, idex + 1);
                s.erase(s.end() - 1);
                used[i] = 0;
            }
        }
    }
    
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> s;
        int depth = nums.size();
        if(depth == 0) return res;
        vector<int> used(depth, 0);//状态标记数组
        dfs(res, used, nums, s, depth, 1);
        return res;
    }
};
  • 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

39. 组合总和

解题思路:

如下

/*
回溯 + 贪心
step1: 
将给定数组进行排序
step2:
先一直加入当前位置最大值,直至等于target或者超过target
    step2.1: 等于target: 加入该种情况,将该数字标记为已使用(即pos + 1, 到下一个比当前值小的值),返回上一级
    step2.2: 大于target: 将数字标记为已使用,返回上一级
*/
class Solution {
public:
    void dfs(vector<vector<int>>& res, vector<int>& candidates, int& pos, vector<int>& s, int target, int& sum){
        if(sum == target){
            res.push_back(s);
            return;
        }
        else if(sum > target) return;
        //保存传入位置,离开此次循环时需要重置回初始环境
        int tmp = pos;
        for(int i = pos; i < candidates.size(); i++){
            s.push_back(candidates[i]);
            dfs(res, candidates, pos, s, target, sum += candidates[i]);
            pos++;
            s.erase(s.end() - 1);
            sum -= candidates[i];
        }
        //重置为初始环境
        pos = tmp;
    }
    
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        vector<int> s;
        sort(candidates.begin(), candidates.end(), greater<int>());
        int sum = 0, pos = 0;
        dfs(res, candidates, pos, s, target, sum);
        return res;
    }
};
  • 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

17. 电话号码的字母组合

解题思路:

很简单的回溯算法思路

/*
回溯算法即可,很简单的一道题
*/
class Solution {
public:
    vector<string> al = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    void dfs(vector<string>& res, string& digits, int posOfDig, int posInside,string& s){
        if(posOfDig == digits.size()){
            res.push_back(s);
            return;
        }
        int num = digits[posOfDig] - '0';
        int digSize = al[num - 2].size();
        for(int i = posInside; i < digSize; i++){
            s.push_back(al[num - 2][i]);
            if(posOfDig < digits.size()){
                dfs(res, digits, posOfDig + 1, 0, s);
            }
            s.erase(s.end() - 1);
        }
    }
    
    vector<string> letterCombinations(string digits) {
        vector<string> res;
        if(digits.size() == 0) return res;
        string s;
        dfs(res, digits, 0, 0, s);
        return res;
    }
};
  • 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

301. 删除无效的括号

HARD: SKIP


  • 1

78. 子集

解题思路:

如下

//包含所有无序的版本
class Solution {
public:
    void dfs(vector<vector<int>>& res, vector<int>& nums, vector<int>& used, vector<int>& add){
        if(add.size() == nums.size()) return;
        for(int i = 0; i < nums.size(); i++){
            if(used[i] == 0){
                add.push_back(nums[i]);
                res.push_back(add);
                used[i] = 1;
                dfs(res, nums, used, add);
                used[i] = 0;
                add.erase(add.end() - 1);
            }
        }
    }
    
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> empty;
        res.push_back(empty);
        vector<int> used(nums.size(), 0);
        vector<int> add;
        dfs(res, nums, used, add);
        return res;
    }
};
  • 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
//顺序版本
class Solution {
public:
    void dfs(vector<vector<int>>& res, vector<int>& nums, int& pos, vector<int>& add){
        if(pos == nums.size()) return;
        int tmp = pos;
        for(int i = pos; i < nums.size(); i++){
            add.push_back(nums[i]);
            res.push_back(add);
            dfs(res, nums, pos += 1, add);
            add.erase(add.end() - 1);
        }
        pos = tmp;
    }
    
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> empty;
        res.push_back(empty);
        vector<int> add;
        int pos = 0;
        dfs(res, nums, pos, add);
        return res;
    }
};
  • 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

79. 单词搜索

解题思路:

class Solution {
public:
    bool dfsCheck(vector<vector<char>>& board, string& word, int posOfWord, vector<vector<int>>& used, int x, int y){
        //检测数组越界
        if(x < 0 || x == board.size() || y < 0 || y == board[0].size()) return false;
        //检测对应字母是否已经被使用或者不正确
        if(used[x][y] == 1 || board[x][y] != word[posOfWord]) return false;
        used[x][y] = 1;
        //检测是否到了最后一位
        if(posOfWord == word.size() - 1) return true;
        bool ret =  dfsCheck(board, word, posOfWord + 1, used, x - 1, y)
                || dfsCheck(board, word, posOfWord + 1, used, x + 1, y)
                || dfsCheck(board, word, posOfWord + 1, used, x, y - 1)
                || dfsCheck(board, word, posOfWord + 1, used, x, y + 1);
        if(!ret) used[x][y] = 0; 
        return ret;
    }
    
    bool exist(vector<vector<char>>& board, string word) {
        vector<int> tmp(board[0].size(), 0);
        vector<vector<int>> used(board.size(), tmp);//设置标记
        int num1 = board.size();
        int num2 = board[0].size();
        for(int i = 0; i < board.size(); i++){
            for(int j = 0; j < board[0].size(); j++){
                if(dfsCheck(board, word, 0, used, i, j)) return true;
            }
        }
        return false;
    }
};
  • 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

494. 目标和

解题思路:

回溯非最优思路

class Solution {
public:
    //若为减号,mul为-1,若为加号,mul为+1
    //sum为表达式的和
    //count为满足要求的数量
    void dfs(vector<int>& nums, int& target, int sum, int posOfNums, int mul, int& count){
        sum += mul * nums[posOfNums];
        if(posOfNums == nums.size() - 1){
            if(sum == target) count++;
            return;
        }
        dfs(nums, target, sum, posOfNums + 1, 1, count);
        dfs(nums, target, sum, posOfNums + 1, -1, count);
    }
    
    int findTargetSumWays(vector<int>& nums, int target) {
        int count = 0;
        dfs(nums, target, 0, 0, 1, count);
        dfs(nums, target, 0, 0, -1, count);
        return count;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

动态规划思路:

    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/454188
    推荐阅读
    相关标签
      

    闽ICP备14008679号