算法日记:穷举vs暴搜vs深搜vs回溯vs剪枝--全排列

🎬 胖咕噜的稞达鸭个人主页
🔥 个人专栏 : 《数据结构《C++初阶高阶》
《Linux系统学习》
《算法日记》

⛺️技术的杠杆,撬动整个世界!


全排列:

全排列

算法原理:

穷举--枚举

两数之和->两层 for 循环

  1. 画出决策树:

  2. 设计代码

    用一个全局变量:int[][]ret;来记录最终的结果;int[] path;对决策树进行深度优先遍历的时候记录一下路径;bool[]check;判断这条路径中此时这个位置的数字是否被使用过了,没有用过就添加进path,用check来实现剪枝。
    dfs函数:仅需关心某一个节点在干什么事情。
    细节问题:
    回溯 :向上走的时候,干掉path的最后一个元素;修改check数组。
    剪枝
    递归出口:遇到叶子节点的时候直接添加结果。

  3. 代码直译:

cpp 复制代码
class Solution 
{
    vector<vector<int>> ret;//返回最后的结果
    vector<int> path;//记录路径
    bool check[7];//标记这个位置是否使用过,数组的下标
public:
    vector<vector<int>> permute(vector<int>& nums)
    {
        dfs(nums);//深度优先遍历
        return ret;
    }
    void dfs(vector<int>& nums)
    {
        if(nums.size() ==  path.size())// 终止条件:当前路径长度等于数组长度 → 找到一个完整排列
        {
            ret.push_back(path);//插入到ret返回数组中
            return;
        }

        for(int i = 0; i < nums.size();i++)
        {
            if(check[i] == false)//数字还没有用过,check数组表示元素有没有被使用过
            {
                path.push_back(nums[i]);//没有使用过插入到数组中
                check[i] = true;//标记为插入过了
                dfs(nums);
                //回溯--->恢复现场
                path.pop_back();//弹出
                check[i] = false;//标记为没插入,等下一轮
            }
        }
    }
};

全排列二:

全排列II

这道题比上一道题多了一个剪枝的操作。

  1. 同一个节点的所有分支中,相同的元素只能选择一次。
  2. 同一个数只能使用一次--->check
  3. 只关心"不合法"的分支:
bash 复制代码
check[i] == true || ((i != 0) && nums[i] == nums[i - 1] && check[i] == fasle);

第一种不合法的情况:

cpp 复制代码
(check[i] == true)i这个数字在之前已经使用过了

第二种不合法的情况:

bash 复制代码
(nums[i]==nums[i-1]) 而且 第二个同样的数字又出现了(check[i] == fasle;),

这个数字还不能是数组第一个元素(i != 0)处理[1,1,2,1],[1,2,1,3,1]这种数组,第二个1已经出现过了,第一次要剔除两个1留下[1,2]进行广度遍历。所以首先要把数组进行排序。
不合法的条件

元素已经进去过的;

当前元素等于上一个元素,而且还是 进去过的(也就是说不可以重复进入)

  1. 还要只关心"合法"的分支(什么时候才进入dfs中)``
bash 复制代码
check[i] == false && ( i = 0  ||  nums[i] != nums[i -1] || check[i - 1] == true):

就是说合法可以进入路径的元素符合以下条件:

元素没进去过的;

当前元素跟上一个元素不同的;

虽然跟上一个数字相同但是目前元素没进去过的

  1. 代码直译:
cpp 复制代码
class Solution {
    vector<vector<int>>ret;
    vector<int>path;
    bool check[9];
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) 
    {
        sort(nums.begin(),nums.end());//先排序
        dfs(nums,0);//从0的位置开始选择
        return ret;
    }
    void dfs(vector<int>& nums,int pos)
    {
        if(pos == nums.size())
        {
            ret.push_back(path);
            return;
        }
        for(int i = 0;i < nums.size();i++)
        {
            //剪枝
            //如果位置不合法,我们就直接跳过:已经进去过的;当前元素和上一个相同的 而且 上一个元素也进去过的
            if(check[i] == true || (i != 0 && nums[i] == nums[i - 1] && check[i - 1] == false))
                continue;
            //位置合法就进去:还没进去过的; 当前元素和上一个元素相同但是上一个元素进去过此时的元素没进去过 ;当前元素不等于上一个元素的
            //(check[i] == false && check[i - 1] == true || nums[i] != nums[i-1] || i = 0)
                path.push_back(nums[i]);
                check[i] = true;
                dfs(nums,pos + 1);
                path.pop_back();//恢复
                check[i] = false;
        }
    }
};
相关推荐
Old Uncle Tom1 小时前
OpenClaw 记忆系统 -- 记忆预加载
java·数据结构·算法·agent
会编程的土豆2 小时前
洛谷题单入门1 顺序结构
数据结构·算法·golang
生信碱移2 小时前
PACells:这个方法可以鉴定疾病/预后相关的重要细胞亚群,作者提供的代码流程可以学习起来了,甚至兼容转录组与 ATAC 两种数据类型!
人工智能·学习·算法·机器学习·数据挖掘·数据分析·r语言
智者知已应修善业2 小时前
【51单片机中的打飞机设计】2023-8-25
c++·经验分享·笔记·算法·51单片机
智者知已应修善业4 小时前
【51单片机按键调节占空比3位数码管显示】2023-8-24
c++·经验分享·笔记·算法·51单片机
.5485 小时前
## Sorting(排序算法)
python·算法·排序算法
wuweijianlove5 小时前
算法的平均复杂度建模与性能回归分析的技术7
算法·数据挖掘·回归
子琦啊5 小时前
【算法复习】字符串 | 两个底层直觉,吃透高频题
linux·运维·算法
code_pgf7 小时前
Octo 算法详解-开源通用机器人策略模型技术报告
算法·机器人·开源
嘻嘻哈哈樱桃7 小时前
牛客经典101题题解集--动态规划
java·数据结构·python·算法·职场和发展·动态规划