LeetCode题解 19(78,494) 子集,目标和<回溯>

子集(78)

在这里插入图片描述
这道题要求我们返回指定数组的所有子集,而且要求不能包含重复的子集。
因此这道题我们依旧采用回溯算法
(一): 我们先定义结果:

List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();

每个子集都是一个list集合,我们没获取到一个子集就对应一个list集合,同时我们就将这list集合加入到res中去,这里我们定义一个start指针从数组的索引0开始,最后只需要返回一个res即可。

    public List<List<Integer>> subsets(int[] nums) {
         res.add(new ArrayList<Integer>(list));
         helper(nums,0);
         return res;
    }

接着我们只需要编写回溯部分的代码,根据回溯的模板:
(一):当start指针到达数组的边界时就表示结束,这也是递归的终止条件。

        if(start >= nums.length){
            return;
        }

(二):for循环体,我们从start的位置开始遍历,将每个元素也就是nums[i],加入到list集合中去,当我们没获取到一个list集合就将list集合加入到res中。因为每个元素都不能重复,因此我们下次递归的start的值就是i+1,最后回退到最初的list就完成了。

        for(int i=start;i<nums.length;i++){
            list.add(nums[i]);
            res.add(new ArrayList<Integer>(list));
            helper(nums,i+1);
            list.remove(list.size()-1);
        }

代码解答

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    public List<List<Integer>> subsets(int[] nums) {
         res.add(new ArrayList<Integer>(list));
         helper(nums,0);
         return res;
    }
    public void helper(int[] nums,int start){
        if(start >= nums.length){
            return;
        }
        for(int i=start;i<nums.length;i++){
            list.add(nums[i]);
            res.add(new ArrayList<Integer>(list));
            helper(nums,i+1);
            list.remove(list.size()-1);
        }
    }
}

目标和(494)

在这里插入图片描述
这道题让我们从nums中选择数字,并且在前面加上(-)或者(+)使得最后的和为target。
我们将数组的长度len和目标值target放到全局变量的位置,方便后期的调用,同时定义一个结果res。

    int len = 0;
    int target = 0;
    int res = 0;
    public int findTargetSumWays(int[] nums, int target) {
        this.len = nums.length;
        this.target = target;
        back(nums,0,0);
        return res;
    }

我们在back方法里面传入的参数分别为数组nums,和sum,指针index。
当指针达到数组的长度len的时候我们就判断这时的sum和target是否相等,
如果相等就res结果集+1,如果不相等就直接退出,因为已经到头了。
接着我们不断递归+ 和 - 两种

        // 如果整个数组元素都用上了
        if(index == len){
            // 如果是target,那么次数++
            if(sum == target){
                res++;
            }
            // 如果不是直接返回
            return;
        }
        // +
        back(nums,sum + nums[index],index + 1);
        // -
        back(nums,sum - nums[index],index + 1);

代码解答

class Solution {
    // 如果使用回溯暴力搜索,每个数组元素无非 + -,时间复杂度为2 ^ n
    int len = 0;
    int target = 0;
    int res = 0;
    public int findTargetSumWays(int[] nums, int target) {
        this.len = nums.length;
        this.target = target;
        back(nums,0,0);
        return res;
    }
    private void back(int[] nums, int sum, int index){
        // 如果整个数组元素都用上了
        if(index == len){
            // 如果是target,那么次数++
            if(sum == target){
                res++;
            }
            // 如果不是直接返回
            return;
        }
        // +
        back(nums,sum + nums[index],index + 1);
        // -
        back(nums,sum - nums[index],index + 1);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱敲键盘的程序源

你的激励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值