Leetcode分类——递归、回溯、分治

Leetcode分类——递归、回溯、分治

递归与回溯的区别

回溯是一种应用递归算法,递归不是
在这里插入图片描述

Leetcode 78

题目
循环的困难之处在于不好模拟选不选某一个数的过程,即选了一个数,不方便回溯到不选这个数的情况。

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

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

解法一:回溯法

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> list = new ArrayList();//存放结果
        List<Integer> temp = new ArrayList<>();//存放一次完整递归的结果
        //递归放入
        addElem(nums, 0, temp, list);
        return list;
    }

    private void addElem(int[] nums, int n, List<Integer> temp, List<List<Integer>> list) {
        //递归的出口
        if (n >= nums.length) {
            List addTemp = new ArrayList(temp);
            list.add(addTemp);
            //list.add(temp);//关键:如果直接放入temp,则所有结果都等于最后一次放入的情况
            return;
        }

		//放入该元素
        temp.add(nums[n]);
        addElem(nums, n + 1, temp, list);
		//回溯,不放入该元素
        temp.remove(temp.size() - 1);
        addElem(nums, n + 1, temp, list);
    }
}

方法二:位运算
位运算介绍:

  • & 按位与
  • | 按位或
  • ^ 按位异或:相同为0,不同为1
  • ~ 取反
  • << 左移:乘以2
  • >> 右移:除以2

这里的集合有三个元素A、B、C,则三个元素共有2^3=8种组成集合的方式,于是可以用0(000)~7(111)来表示这些集合。

集合整数ABC
{}000=0000
{C}001=1001
{B}010=2010
{B,C}011=3011
{A}100=4100
{A,C}101=5101
{A,B}110=6110
{A,B,C}111=7111

A元素为100=4,B元素为010=2,C元素为001=1。如需判断一个集合是否含有该元素,将这个集合的二进制表示与该元素的二进制表示做**&运算**,结果为真时,表示包含该元素,将其push进集合内。

9-1000000000
8-0100000000
7-0010000000
6-0001000000
5-0000100000
4-0000010000
3-0000001000
2-0000000100
1-0000000010
0-0000000001

9 8 7 6 5 4 3 2 1
组合共有2^10 = 1024

Leetcode 90

题目
利用set将list中相同的list剔除。

class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> list = new ArrayList();
        List<Integer> temp = new ArrayList<>();
        //需要对输入事先排序,使得得到的重复list顺序相同,能够被set认为是重复项
        Arrays.sort(nums);
        addElem(nums, 0, temp, list);
        //将list<list>存为set<list>类型去重,最后转换为list
        return new ArrayList<>(new HashSet<>(list));
    }

    private void addElem(int[] nums, int n, List<Integer> temp, List<List<Integer>> list) {
        if (n >= nums.length) {
            List addTemp = new ArrayList(temp);
            list.add(addTemp);
            return;
        }

        temp.add(nums[n]);
        addElem(nums, n + 1, temp, list);

        temp.remove(temp.size() - 1);
        addElem(nums, n + 1, temp, list);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值