回溯算法的去重问题
创始人
2024-12-28 07:06:13
0

概述

在利用回溯算法去求子集、排列、组合等问题时,所给数组中如果包含重复元素,需要进行去重操作。常用的去重方法是使用used数组或集合。

对于上述子集、排列、组合等问题的求解方法是将数组转化为的形式,利用递归和回溯的方法进行求解。去重操作主要处理的是在同一层的数据的重复操作。

例如:力扣90题子集问题,将其转换为树的形式以及去重操作示意图如下

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的 

子集

(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

示例 1:

输入:nums = [1,2,2] 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]] 

示例 2:

输入:nums = [0] 输出:[[],[0]]

used方法为设置一个bool类型的数组,数组中元素如果为false则表示在同一层使用过,如果为true表示在同一树枝(纵向)使用过。如果用set集合的方式,则如果索引到的元素在集合出现过,则表示在同一层使用过。两者不同的是used数组在函数参数定义及函数外定义,所占空间内存小,为O(n),set集合在函数中for循环外定义,每次递归需要再次展开内存,所占空间大,为O(n*2)。

例题

集合

数组形式,注意要进行排序

class Solution { private:     vector> result;     vector path;     void backtracking(vector& nums, int startIndex, vector& used) {         result.push_back(path);         for (int i = startIndex; i < nums.size(); i++) {             // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过             // used[i - 1] == false,说明同一树层candidates[i - 1]使用过             // 而我们要对同一树层使用过的元素进行跳过             if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {                 continue;             }             path.push_back(nums[i]);             used[i] = true;             backtracking(nums, i + 1, used);             used[i] = false;             path.pop_back();         }     }  public:     vector> subsetsWithDup(vector& nums) {         result.clear();         path.clear();         vector used(nums.size(), false);         sort(nums.begin(), nums.end()); // 去重需要排序         backtracking(nums, 0, used);         return result;     } };

集合形式

void trversal(vector&nums,int index)     {          result.push_back(path);         if(index>=nums.size())             return;         unordered_setuset;         for(int i=index;i> subsetsWithDup(vector& nums) {         result.clear();         path.clear();        // vectorused(nums.size(),false);         sort(nums.begin(),nums.end());         trversal(nums,0);         return result;     } };

全排列

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:

  • 输入:nums = [1,1,2]
  • 输出: [[1,1,2], [1,2,1], [2,1,1]]

示例 2:

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

提示:

  • 1 <= nums.length <= 8
  • -10 <= nums[i] <= 10

对于排列问题,和集合问题的不同点在于for循环的开始位置不同,集合问题为当前元素的下一个元素的位置,而排列问题一直为数组的起始位置,需要注意的是要加上元素是否使用的判断。

代码如下

class Solution { private:     vector> result;     vector path;     void backtracking (vector& nums, vector& used) {         // 此时说明找到了一组         if (path.size() == nums.size()) {             result.push_back(path);             return;         }         for (int i = 0; i < nums.size(); i++) {             // used[i - 1] == true,说明同一树枝nums[i - 1]使用过             // used[i - 1] == false,说明同一树层nums[i - 1]使用过             // 如果同一树层nums[i - 1]使用过则直接跳过             if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {                 continue;             }             if (used[i] == false) {//未在树枝使用,可以加入到path数组中                 used[i] = true;                 path.push_back(nums[i]);                 backtracking(nums, used);                 path.pop_back();                 used[i] = false;             }         }     } public:     vector> permuteUnique(vector& nums) {         result.clear();         path.clear();         sort(nums.begin(), nums.end()); // 排序         vector used(nums.size(), false);         backtracking(nums, used);         return result;     } };  // 时间复杂度: 最差情况所有元素都是唯一的。复杂度和全排列1都是 O(n! * n) 对于 n 个元素一共有 n! 中排列方案。而对于每一个答案,我们需要 O(n) 去复制最终放到 result 数组 // 空间复杂度: O(n) 回溯树的深度取决于我们有多少个元素

相关内容

热门资讯

第九分钟辅助!天天爱柳州辅助器... 天天爱柳州辅助器是一款可以让一直输的玩家,快速成为一个“必胜”的ai辅助神器,有需要的用户可以加我微...
热门推荐!微信小程序蜀山辅助器... 热门推荐!微信小程序蜀山辅助器免费下载(辅助)外挂辅助开挂插件(有挂秘诀)-哔哩哔哩;最新版2026...
第4分钟普及!奇迹陕西辅助器(... 第4分钟普及!奇迹陕西辅助器(透视)原来真的是有挂脚本(推荐开挂软件);奇迹陕西辅助器免费下载原版,...
第八分钟讲解!越乡游金花辅助,... 第八分钟讲解!越乡游金花辅助,九酷众游辅助,细节方法(有挂实锤)-哔哩哔哩1、下载安装好越乡游金花辅...
透视软件!浙江宝宝游戏辅助工具... 透视软件!浙江宝宝游戏辅助工具(辅助)外挂开挂辅助插件(了解有挂)-哔哩哔哩;是一款可以让一直输的玩...
第5分钟发现!桃乐甘肃麻将下载... 《第5分钟发现!桃乐甘肃麻将下载辅助器(辅助)原来有挂软件(必看开挂工具)》 桃乐甘肃麻将下载辅助器...
第8分钟了解!河洛刚次辅助,温... 第8分钟了解!河洛刚次辅助,温州茶苑辅助软件,详细教程(有挂攻略)-哔哩哔哩;无需打开直接搜索加薇1...
热点讨论!新二号辅助软件下载(... 热点讨论!新二号辅助软件下载(辅助)外挂辅助开挂软件(有挂教程)-哔哩哔哩;是一款可以让一直输的玩家...
8分钟解说!网易亲友圈辅助(开... 8分钟解说!网易亲友圈辅助(开挂)原来有挂平台(必看开挂安装);小薇(透视辅助)致您一封信;亲爱网易...
第5分钟开挂!如何在哈灵上辅助... 第5分钟开挂!如何在哈灵上辅助,决战卡五星辅助看牌器,解说技巧(有挂方略)-哔哩哔哩 了解更多开挂安...