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

2022-10-25 16:04:47 浏览数 (1)

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

  • 递归与回溯的区别
  • Leetcode 78
  • Leetcode 90

递归与回溯的区别

回溯是一种应用递归算法,递归不是

Leetcode 78

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

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

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

解法一:回溯法

代码语言:javascript复制
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)来表示这些集合。

集合

整数

A

B

C

{}

000=0

0

0

0

{C}

001=1

0

0

1

{B}

010=2

0

1

0

{B,C}

011=3

0

1

1

{A}

100=4

1

0

0

{A,C}

101=5

1

0

1

{A,B}

110=6

1

1

0

{A,B,C}

111=7

1

1

1

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

代码语言:javascript复制
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剔除。

代码语言:javascript复制
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);
    }
}

0 人点赞