【leetcode】深搜、暴搜、回溯、剪枝(C++)2

这篇具有很好参考价值的文章主要介绍了【leetcode】深搜、暴搜、回溯、剪枝(C++)2。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、括号生成

1、题目描述

leetcode链接
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

class Solution 
{
public:
    // 1、全局变量
    string path;
    vector<string> ret;
    int right = 0, left = 0, n = 0;
    vector<string> generateParenthesis(int _n) 
    {
        n = _n;
        dfs();
        return ret;
    }
    void dfs()
    {
        // 1、出口
        if(right == n)
        {
            ret.push_back(path);
            return;
        }
        // 2、添加左括号
        if(left < n)
        {
            path.push_back('(');
            left++;
            dfs();
            path.pop_back(); // 恢复现场
            left--;
        }
        if(right < left) // 3、添加右括号
        {
            path.push_back(')');
            right++;
            dfs();
            path.pop_back(); // 恢复现场
            right--;
        }
    }
};

3、解析

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

二、组合

1、题目描述

leetcode链接

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

class Solution 
{
public:
    // 1、全局变量
    int n = 0; // 1-n
    int k = 0; // 几个数
    vector<int> path; // 路径
    vector<vector<int>> ret; // 增加的路径函数
    vector<vector<int>> combine(int _n, int _k) 
    {
        n = _n;
        k = _k;
        dfs(1); // 2、dfs
        return ret;
    }
    void dfs(int _pos)
    {
        // 1、函数递归出口
        if(path.size() == k)
        {
            ret.push_back(path);
            return;
        }
        // 2、遍历--剪枝
        for(int pos = _pos; pos <= n; pos++)
        {
            path.push_back(pos);
            dfs(pos + 1); // pos下一个数进行递归实现剪枝
            path.pop_back(); // 回溯--恢复现场         
        }
    }
};

3、解析

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

三、目标和

1、题目描述

leetcode链接
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

全局变量的超时代码:
原因在于nums的长度最长有20,其2^20次方太大了。但是leetcode居然通过了。

class Solution 
{
public:
    // 1、全局变量
    int ret; // 返回
    int aim; // 目标值
    int path; // 路径
    int findTargetSumWays(vector<int>& nums, int target) 
    {
        aim = target;
        dfs(nums, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos)
    {
        // 1、递归出口
        if(pos == nums.size())
        {
            if(path == aim)
            {
                ret++;
            }
            return;
        }
        // 2、加法
        path += nums[pos];
        dfs(nums, pos + 1);
        path -= nums[pos]; // 恢复现场
        // 3、减法
        path -= nums[pos];
        dfs(nums, pos + 1);
        path += nums[pos]; // 恢复现场
    }
};

path作为参数的正确代码:

class Solution 
{
public:
    // 1、全局变量
    int ret; // 返回
    int aim; // 目标值
    int findTargetSumWays(vector<int>& nums, int target) 
    {
        aim = target;
        dfs(nums, 0, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos, int path)
    {
        // 1、递归出口
        if(pos == nums.size())
        {
            if(path == aim)
            {
                ret++;
            }
            return;
        }
        // 2、加法
        path += nums[pos];
        dfs(nums, pos + 1, path);
        path -= nums[pos]; // 恢复现场
        // 3、减法
        path -= nums[pos];
        dfs(nums, pos + 1, path);
        path += nums[pos]; // 恢复现场
    }
};

3、解析

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

四、组合总和

1、题目描述

leetcode链接
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

解法一:

class Solution 
{
public:
    // 1、全局变量
    vector<vector<int>> ret; // 返回
    vector<int> path; // 路径
    int aim; // 记录target
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) 
    {
        aim = target;
        dfs(candidates, 0, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos, int sum)
    {
        // 1、递归出口
        if(sum == aim)
        {
            ret.push_back(path);
            return;
        }
        if(sum > aim)
        {
            return;
        }
        // 循环
        for(int i = pos; i < nums.size(); i++)
        {
            path.push_back(nums[i]);
            sum += nums[i];
            dfs(nums, i, sum); // 还是从开始
            path.pop_back(); // 恢复现场
            sum -= nums[i];
        }
    }
};

解法二:

class Solution 
{
public:
    // 1、全局变量
    vector<vector<int>> ret; // 返回
    vector<int> path; // 路径
    int aim; // 记录target
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) 
    {
        aim = target;
        dfs(candidates, 0, 0);
        return ret;
    }
    void dfs(vector<int>& nums, int pos, int sum)
    {
        // 1、递归出口
        if(sum == aim)
        {
            ret.push_back(path);
            return;
        }
        if(sum > aim || pos == nums.size())
        {
            return;
        }
        // 循环
        for(int k = 0; k * nums[pos] + sum <= aim; k++)
        {
            if(k)
            {
                path.push_back(nums[pos]);
            }
            dfs(nums, pos + 1, sum + k * nums[pos]);
        }
        // 恢复现场
        for(int k = 1; k * nums[pos] + sum <= aim; k++)
        {
            path.pop_back();
        }
    }
};

3、解析

解法一:
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先
解法二:
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

五、字母大小写全排列

1、题目描述

leetcode链接
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

class Solution 
{
public:
    // 全局变量
    string path; // 路径
    vector<string> ret; // 返回
    vector<string> letterCasePermutation(string s) 
    {
        dfs(s, 0); // 将s这个字符串的第0个位置进行传参
        return ret;
    }
    void dfs(string s, int pos)
    {
        // 递归出口
        if(pos == s.length())
        {
            ret.push_back(path);
            return;
        }
        // 先记录一下当前的字母
        char ch = s[pos];
        // 不改变
        path.push_back(ch);
        dfs(s, pos + 1);
        path.pop_back(); // 恢复现场
        // 改变
        if(ch < '0' || ch > '9')
        {
            // 进行改变大小写函数
            ch = Change(ch);
            path.push_back(ch);
            dfs(s, pos + 1); // 往下一层递归
            path.pop_back(); // 恢复现场
        }
    }
    char Change(char ch)
    {
        if(ch >= 'a' && ch <= 'z')
        {
            ch -= 32;
        }
        else
        {
            ch += 32;
        }
        return ch;
    }
};

3、解析

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

六、优美的排列

1、题目描述

leetcode链接
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

class Solution 
{
public:
    // 全局变量
    int ret; // 返回
    bool check[16]; // 判断相对应位置是true还是false
    int countArrangement(int n) 
    {
        dfs(1, n); // 下标从1开始
        return ret;
    }
    void dfs(int pos, int n)
    {
        // 递归出口
        if(pos == n + 1) // 因为是从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); // 递归到下一层
                check[i] = false; // 恢复现场
            }
        }
    }
};

3、解析

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

七、N皇后

1、题目描述

leetcode链接

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

class Solution 
{
public:
    // 全局变量
    bool checkcol[10]; // 列
    bool checkG1[20]; // 主对角线
    bool checkG2[20]; // 副对角线
    vector<string> path; // 路径
    vector<vector<string>> ret; // 返回
    int n; // 全局变量n
    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;
    }
    void dfs(int row) // 行
    {
        // 递归出口
        if(row == n)
        {
            ret.push_back(path);
            return;
        }
        for(int col = 0; col < n; col++) // 每一行所在的列位置
        {
            if(checkcol[col] == false/*一整列*/ && checkG1[row - col + n] == false/*y-x+n*/ && checkG2[row + col] == false/*y+x*/) // 判断条件进入
            {
                path[row][col] = 'Q';
                checkcol[col] = checkG1[row - col + n] = checkG2[row + col] = true;
                dfs(row + 1);
                // 恢复现场
                path[row][col] = '.';
                checkcol[col] = checkG1[row - col + n] = checkG2[row + col] = false;
            }
        }
    }
};

3、解析

这里我们着重在剪枝方面上面的讲解,我们重点需要明白N皇后剪枝的作用,因为皇后是能吃横的一整行,竖的一整列,主对角线和副对角线一整个,这里原本是要循环四次,但是我们经过想法发现其实只需要判断三个位置即可,第一个位置是竖着的,第二个位置是主对角线,第三个位置是副对角线,因为横着的一行是不需要进行判断的,因为我们的思路是以一整行为一个视角,从左往右依次填的!我们根据简单的数学原理,主对角线是y=x+b的,而由于会出现负数情况,我们左右两边各加一个n即可,我们此时b就为:y-x+n。我们副对角线是y=-x+b,我们的b为y+x即可!那我们接下来的思路画出决策树以后只需要考虑回溯的问题,我们恢复现场只需要将用过的全部变成没用过的即可。
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

八、有效的数独

1、题目描述

leetcode链接
【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先

2、代码

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] == true || col[j][num] == true || grid[i / 3][j / 3][num] == true)
                    {
                        return false;
                    }
                    row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = true;
                }
            }
        }
        return true;
    }
};

3、解析

【leetcode】深搜、暴搜、回溯、剪枝(C++)2,C++刷题,leetcode,剪枝,c++,算法,深度优先文章来源地址https://www.toymoban.com/news/detail-830305.html

到了这里,关于【leetcode】深搜、暴搜、回溯、剪枝(C++)2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 穷举&&深搜&&暴搜&&回溯&&剪枝(2)

    一)电话号码的字母组合 17. 电话号码的字母组合 - 力扣(LeetCode) 1)画出决策树:只是需要对最终的决策树做一个深度优先遍历,在叶子节点收集结果即可 把图画出来,知道每一层在干什么,代码就能写出来了  2)定义全局变量: 1)定义一个哈希表来处理数字和字符串的映射关系

    2024年02月14日
    浏览(44)
  • LeetCode刷题13:回溯+剪枝解决216.组合总和 III

    找出所有相加之和为  n   的  k   个数的组合,且满足下列条件: 只使用数字1到9 每个数字  最多使用一次   返回  所有可能的有效组合的列表  。该列表不能包含相同的组合两次,组合可以以任何顺序返回。 示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]] 解释: 1 + 2 + 4 = 7 没有其他

    2024年02月02日
    浏览(44)
  • DFS:深搜+回溯+剪枝解决组合问题

                                                   创作不易,感谢支持!!! . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) 该题和前面是类似的,但是用回溯算法,会超

    2024年04月12日
    浏览(39)
  • DFS:深搜+回溯+剪枝解决排列、子集问题

                                        创作不易,感谢三连支持!!  . - 力扣(LeetCode) . - 力扣(LeetCode)  方案1:不合法就continue 方案2:合法才能进循环 . - 力扣(LeetCode) . - 力扣(LeetCode)  策略1:决策树以选不选作为参考,结果为叶子节点 策略2:决策树以选几个

    2024年04月16日
    浏览(66)
  • DFS:深搜+回溯+剪枝解决矩阵搜索问题

                                                   创作不易,感谢三连!!  . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) . - 力扣(LeetCode) 1、矩阵搜索问题经常要用到向量,也就是我们可以通过dx和dy来帮助我们定义方向

    2024年04月17日
    浏览(41)
  • 【算法】递归、回溯、剪枝、dfs 算法题练习(组合、排列、总和问题;C++)

    后面的练习是接着下面链接中的文章所继续的,在对后面的题练习之前,可以先将下面的的文章进行了解👇: 【算法】{画决策树 + dfs + 递归 + 回溯 + 剪枝} 解决排列、子集问题(C++) 思路 题意分析 :要求根据给出的数字,算出合法的括号组成个数。根据题目,我们可以总

    2024年02月22日
    浏览(50)
  • 【leetcode刷题之路】剑指Offer(3)——搜索与回溯算法

    7 搜索与回溯算法 7.1 【BFS】剑指 Offer 32 - I - 从上到下打印二叉树 https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/   这里借助队列来实现广度优先遍历,由于需要访问每一层的节点,而且这一层访问才可以访问下一层,所以可以考虑队列的先进先出,先把每一层的节

    2024年02月13日
    浏览(59)
  • 递归、搜索与回溯算法(专题二:深搜)

    往期文章(希望小伙伴们在看这篇文章之前,看一下往期文章) (1)递归、搜索与回溯算法(专题零:解释回溯算法中涉及到的名词)【回溯算法入门必看】-CSDN博客 (2)递归、搜索与回溯算法(专题一:递归)-CSDN博客  深搜是实现递归的一种方式,接下来我们之间从题

    2024年01月20日
    浏览(81)
  • LeetCode 39. 组合总和(回溯+剪枝)

    链接:LeetCode 39. 组合总和 难度:中等 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重复被选

    2024年02月14日
    浏览(45)
  • 递归专题训练详解(回溯,剪枝,深度优先)

    在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制: (1) 每次只能移动一个盘子; (2) 盘子只能从柱子顶端滑出

    2024年02月07日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包