递归与回溯10:子集,有重复元素
Posted 纵横千里,捭阖四方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归与回溯10:子集,有重复元素相关的知识,希望对你有一定的参考价值。
这个题与前面的相比又加码了,如果给定的子集有重复元素该怎么办?先看题目要求:LeetCode90给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。示例:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
这个问题的关键是怎么处理去重的问题,这里卡哥的解析挺好,我们直接节选了:
抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过。没有理解这两个层面上的“使用过” 是造成大家没有彻底理解去重的根本原因。
那么我们是要同一树层上使用过,还是统一树枝上使用过呢?
回看一下题目,元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。
所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。
后面要学习的排列问题里去重也是这个套路,所以理解“树层去重”和“树枝去重”非常重要。
去重时我们一般要先对元素进行排序,这样会容易很多。
从图中可以看出,同一树层上重复取2 就要过滤掉,同一树枝上就可以重复取2,因为同一树枝上元素的集合才是唯一子集!
实现代码:
class Solution
// 存放符合条件结果的集合
List<List<Integer>> result = new ArrayList<>();
// 用来存放符合条件结果
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums)
if (nums.length == 0)
result.add(path);
return result;
Arrays.sort(nums);
used = new boolean[nums.length];
subsetsWithDupHelper(nums, 0);
return result;
private void subsetsWithDupHelper(int[] nums, int startIndex)
result.add(new ArrayList<>(path));
if (startIndex >= nums.length)
return;
for (int i = startIndex; i < nums.length; i++)
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])
continue;
path.add(nums[i]);
used[i] = true;
subsetsWithDupHelper(nums, i + 1);
path.removeLast();
used[i] = false;
以上是关于递归与回溯10:子集,有重复元素的主要内容,如果未能解决你的问题,请参考以下文章