算法3----穷举&暴搜&回溯&剪枝

例一:全排列

题目:给一个不含重复数的数组,返回其所有可能的全排列

示例:

给出一个数组nums[1,2,3],返回其所有的全排列为[1,2,3],[1,3,2],[2,3,1],[2,1,3],[3,1,2],[3,2,1].

方法:

1:画出决策树(一定要先画出决策树来辅助思考)

每一层都是在三选一,然后不可以选中与前几次一样的数

2:设计代码

全局变量

int[][] ret;(表示最终要返回的所有排列)

int[] path;(表示每一条排列,将其记录在path中,再由path放进ret中)

bool[] check;(标记位置,看是否被使用过·,从而决定是否要使用该条路径)

dfs函数(仅需关心某一个节点在做什么)

细节问题

回溯:要将最后一个元素排除,并且将其位置重置

剪枝:利用check[]数组,实现剪枝

递归出口:遇到叶子节点,直接添加结果

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);
            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;
            }
        }
    }
};

例二:子集

题目:给出一个整数数组,元素各不相同,返回其所有的子集

示例:

给出一个数组nums[1,2,3],其所有的子集为:(1)(2)(3)(1 2)(1 3)(2 3)(1 2 3)

方法一:叶子节点为所求的子集

1:画出决策树

每一层都要分两种,选不选当前的数

2:设计代码

全局变量

int [] path;(记录路径)

int[][] ret;(存放结果)

dfs函数

dfs(nums,i)

选的话:path+=nums[i],dfs(nums,i)

不选:dfs(nums,i+1)

递归出口

i==nums.size()

class Solution {
    vector<int> path;
    vector<vector<int>> ret;
public:
    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);


    }

};

方法二:

 1:画决策树

每一层都是所求的子集

2:设计代码

全局变量

int [] path;(记录路径)

int[][] ret;(存放结果)

dfs函数

dfs(nums,pos)(pos表示位置,当前位置该从何处进行枚举)

class Solution {
    vector<int> path;
    vector<vector<int>> ret;
public:
    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();//恢复现场
        }


    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值