Leetcode 递归&回溯

递归&回溯

Pre-Introduction

递归 Recursion

  • 改变输入参数
  • 设置递归结束调用条件

回溯 Backtracting Algorithm

又称试探法, 即走不通就退回再走
当探索到某一步走不动时,发现原先选择达不到目标,就退回一步重新选择.
(用栈是否可以?)

  • 实现某一个元素选择放入还是不放入

  • 递归树

  • 递归树

    • 回到递归的交叉点, 选择另一条线
    • 剪枝
      • 递归增加条件(22)
      • 设置return的条件(40)

递归 vs 回溯

  • 递归: 开发代码的思想
  • 回溯:利用递归的思想的算法
  • 分治: 递归/非递归

22. 括号生成(Medium)

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]

提示:

1 <= n <= 8

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> result;
        generate("", n, n, result);
        return result;
    }
private:
    void generate(string item, int left, int right, vector<string>&result){
        if(left==0&&right==0){
            result.push_back(item);
            return;
        }
        /**
         * 递归增加限制条件
         * 左右括号各自数量不能大于n
         * 右括号不能先于左括号放置(左括号>右括号时, 才能放置右括号)
         * */
        if(left>0){
            generate(item+'(', left-1, right, result);
        }
        if(right>=0&&right>left){
            generate(item+')', left, right-1, result);
        }
    }
};

40. 组合总和 II (Medium)

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

说明:

所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。

示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]

#include <vector>
#include <Algorithm>
#include <set>
using namespace std;

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int> item;
        vector<vector<int>> result;
        set<vector<int>> res_set;
        sort(candidates.begin(), candidates.end());

        find(0, target, 0, candidates, item, result, res_set);
        return result;
    }

private:
    void find(int i, int target, int sum, vector<int>& candidates, vector<int>& item, vector<vector<int>>& result, set<vector<int>>& res_set){

        if(i==candidates.size() || sum>=target){
            if(sum==target){
                if(res_set.find(item)==res_set.end()){
                    result.push_back(item);
                    res_set.insert(item);
                }
            }
            return;
        }
        item.push_back(candidates[i]);
        sum+=candidates[i];
        find(i+1, target, sum, candidates, item, result, res_set);
        sum-=item.back();
        item.pop_back();
        find(i+1, target, sum, candidates, item, result, res_set);
    }
};

78. 子集(Medium)

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]

提示:

1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums 中的所有元素 互不相同

方法1:

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        int size=nums.size();
        int all_set=1<<nums.size();
        vector<vector<int>> result;
        for(int i=0;i<all_set;i++){
            vector<int> item;
            for(int j=0; j<nums.size();j++){
                if(i&(1<<j)){
                    item.push_back(nums[j]);
                }
            }
            result.push_back(item);
        }
        return result;
    }
};

方法2:

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<int> item;
        vector<vector<int>> result;
        result.push_back(item);
        generate(0, nums, item, result);
        return result;
    }
private:
    void generate(int i, vector<int> &nums, vector<int> &item, vector<vector<int>> &result){
        if(i==nums.size()) return;
        item.push_back(nums[i]);
        result.push_back(item);
        generate(i+1, nums, item, result);
        item.pop_back();
        generate(i+1, nums, item, result);
    }
};

90. 子集 II (Medium)

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:
输入: [1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]

class Solution {
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        vector<vector<int>> result;
        vector<int> item;
        set<vector<int>> res_set;
        result.push_back(item);
        sort(nums.begin(), nums.end());
        generate(0, nums, item, result, res_set);
        return result;

    }
private:
    void generate(int i, vector<int>& nums, vector<int>& item, vector<vector<int>>& result, set<vector<int>>& res_set){
        if(i==nums.size()) return;
        item.push_back(nums[i]);
        if(res_set.find(item)==res_set.end()){
            result.push_back(item);
            res_set.insert(item);
        }
        
        generate(i+1, nums, item, result, res_set);
        item.pop_back();
        generate(i+1, nums, item, result, res_set);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值