子集II
給你一個整數數組?
nums
?,找出并返回所有該數組中不同的遞增子序列,遞增子序列中?至少有兩個元素?。你可以按?任意順序?返回答案。數組中可能含有重復元素,如出現兩個整數相等,也可以視作遞增序列的一種特殊情況。
示例 1:
輸入:nums = [4,6,7,7] 輸出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]示例 2:
輸入:nums = [4,4,3,2,1] 輸出:[[4,4]]提示:
1 <= nums.length <= 15
-100 <= nums[i] <= 100
這道題的終止條件是每一次循環時,如果pah如果大于1,那么我們就要進行存入result里,且不寫return,因為這道題不是在葉子節點才存值,而是在每個path的大小大于1就要存進去。
去重的操作也不同,本題去重是使用的哈希表去重,這里我使用的是unordered_set (如果使用數組的話,時間消耗會更少)在for循環內開始如果這個值小于path最后一個值或者之前用過了,就continue。
且這個去重是每層去重,那在回溯過程的話就不需要再刪去uset里面的值?。
class Solution {
public:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums,int startIndex){if(path.size()>1) {result.push_back(path);}unordered_set<int> uset;for(int i = startIndex;i<nums.size();i++){if(!path.empty()&&path.back()>nums[i]||uset.find(nums[i])!=uset.end())continue;path.push_back(nums[i]);uset.insert(nums[i]);backtracking(nums,i+1);path.pop_back();}} vector<vector<int>> findSubsequences(vector<int>& nums) {backtracking(nums,0);return result;}
};
全排列
給定一個不含重復數字的數組?
nums
?,返回其?所有可能的全排列?。你可以?按任意順序?返回答案。示例 1:
輸入:nums = [1,2,3] 輸出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2:
輸入:nums = [0,1] 輸出:[[0,1],[1,0]]示例 3:
輸入:nums = [1] 輸出:[[1]]提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums
?中的所有整數?互不相同
全排列,回溯函數參數就不用寫startIndex,相應的要寫uset,目的是下面for循環中我們要知道每個數是否被使用過。
終止條件是當path的大小,它等于nums的大小,我們就加在result里,然后return。
其余就很常規。
class Solution {
public:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& nums,vector<bool>& used){if(path.size()==nums.size()){result.push_back(path);return ;}for(int i = 0;i<nums.size();i++){if(used[i]==true)continue;used[i]=true;path.push_back(nums[i]);backtracking(nums,used);used[i]=false;path.pop_back();}}vector<vector<int>> permute(vector<int>& nums) {vector<bool> used(nums.size(),false);backtracking(nums,used);return result;}
};
?
全排列 II
給定一個可包含重復數字的序列?
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循環內要再多做一層去重的操作。
我們注意到,排序后,如果nums[i]==nums[i-1]的,且uset[i-1]==false(這種情況就是同層去重),那我們就continue。
這個引用一些代碼隨想錄的片段:
大家發現,去重最為關鍵的代碼為:
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue; }
如果改成?
used[i - 1] == true
, 也是正確的!,去重代碼如下:if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true) {continue; }
這是為什么呢,就是上面我剛說的,如果要對樹層中前一位去重,就用
used[i - 1] == false
,如果要對樹枝前一位去重用used[i - 1] == true
。對于排列問題,樹層上去重和樹枝上去重,都是可以的,但是樹層上去重效率更高!
?
下面給出代碼:
class Solution {
public:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums,vector<bool>& uset){if(path.size()==nums.size()){result.push_back(path);return;}for(int i = 0;i<nums.size();i++){if(i>0&&nums[i-1]==nums[i]&&uset[i-1]==false){continue;}if(uset[i]==false){uset[i]=true;path.push_back(nums[i]);backtracking(nums,uset);path.pop_back();uset[i]=false;}}}vector<vector<int>> permuteUnique(vector<int>& nums) {sort(nums.begin(),nums.end());vector<bool> uset(nums.size(),false);backtracking(nums,uset);return result;}
};
今天實在太忙,寫的少了些,諒解。?
?