算法基础/递归回溯

本文介绍了如何使用迭代和递归方法解决给定数组的所有子集(幂集)问题,包括处理重复元素的情况。示例展示了如何在C++中实现这两种方法,并提供了详细的解题思路和代码实现。对于存在重复元素的子集问题,解决方案是先对数组排序,然后在递归过程中避免重复子集的生成。
摘要由CSDN通过智能技术生成

背下来 !!当模板用!!

1.78. 子集

题目描述:

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

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

示例:

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

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


解答描述:

要求解所有可能的子集,有两种方法,迭代和递归。

关键在于理解:每个元素要么在子集中,要么不在子集中。

1)迭代:

在迭代法中,用长为n的01序列来表示各个元素被选中的情况,共有2^n个序列表示2^n的子集。

2)递归:

背下来 ,当模板,从下标为0开始递归,每个元素要么被选中,要么不被选中,当递归到n的时候将结果压入结果数组中,表示一个子集生成。


代码:

class Solution {
public:
    vector<vector<int>> ans;
    vector<int> temp;
    
    vector<vector<int>> subsets(vector<int>& nums) {
        //每个元素ai要么在子集中,要么不在子集中
        int n=nums.size();
        for(int i=0;i<pow(2,n);i++)//共2^n个子集
        {
            temp.clear();
            for(int j=0;j<n;j++)//每个子集可用一个长为n的01序列表示
            {
                if(i & (1<<j))
                {
                    temp.push_back(nums[j]);
                }
            }
            ans.push_back(temp);
        }
        return ans;
    }
};
class Solution {
public:
    vector<vector<int>> ans;
    vector<int> temp;
    void DFS(vector<int>& nums,int index)
    {
        if(index==nums.size())
        {
            ans.push_back(temp);
            return;
        }
        //a_index在子集中
        temp.push_back(nums[index]);
        DFS(nums,index+1);
        //a——index不在子集中
        temp.pop_back();
        DFS(nums,index+1);
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        //每个元素ai要么在子集中,要么不在子集中
        DFS(nums,0);
        return ans;
    }
};

2.90. 子集 II

题目描述:

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

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

示例:

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

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


解答描述:

该题与上一题的区别在于:可能存在重复元素,所以需要进行去重。

去重的方式就是:先进行排序,将相同的元素放在邻近的位置,如果迭代\递归的时候发现没有选择上一个数,且上一个数和当前数相同,那么意味着这轮需要被跳过。


代码:

class Solution {
public:
    vector<vector<int>> ans;
    vector<int> temp;
    //在递归时,若发现没有选择上一个数,且当前数字与上一个数相同,则可以跳过当前生成的子集。
    void DFS(vector<int> &nums,int index,bool choose)//choose标记上一个数组是否被选中
    {
        if(index==nums.size())
        {
            ans.push_back(temp);
            return ;
        }
        //a_i不在子集中
        DFS(nums,index+1,false);
        if(choose==false && index>0 && nums[index]==nums[index-1])
        {
            return;
        }
        //a_i在子集中
        temp.push_back(nums[index]);
        DFS(nums,index+1,true);
        temp.pop_back(); 
    }
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        //先对数组进行排序
        sort(nums.begin(),nums.end());
        DFS(nums,0,false);
        return ans;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值