leetcode/notes/src/subsets.md

1.8 KiB

子集问题

子集问题:一个 N 个数的集合里有多少符合条件的子集

78. 子集

其实和切割问题非常像。

90. 子集 II

就是在 s0078 的基础上加了去重逻辑,和组合问题中的去重逻辑一样。

491. 递增子序列

也是要去重,但是不能通过排序去重,因为排序之后顺序就全部打乱了。

这个去重同样要保留树枝重复,但去除树层重复。

思路很简单,每一层遍历的时候创建一个哈希表,用来记录当前元素是否遍历过,如果遍历过则跳过。

void findSubsequencesDFS(vector<int> &subsequences, vector<vector<int>> &result,
                         vector<int> &nums, int startIndex) {
  int size = nums.size();
  // 结束条件
  if (startIndex == size) return;

  // 初始化一个哈希表用来存储元素是否在数层中使用过
  unordered_map<int, bool> used;

  for (int i = startIndex; i < size; ++i) {
    // 剪枝,如果元素在数层中使用过则跳过
    if (used.count(nums[i]) == 1) continue;
    // 当当前元素大于等于起始元素之前的元素时,将它添加进去
    if (startIndex == 0 || nums[i] >= nums[startIndex - 1]) {
      subsequences.push_back(nums[i]);
      if (subsequences.size() > 1) result.push_back(subsequences);
      used[nums[i]] = true;
      findSubsequencesDFS(subsequences, result, nums, i + 1);
      subsequences.pop_back();
    }
  }
}

这种去重逻辑相比于之前的去重逻辑起始开销更大,因为每一层遍历都要创建一个新的哈希表,而之前的去重逻辑每一层遍历都用的是之前创建的向量。