題目
給定一個整型數組, 你的任務是找到所有該數組的遞增子序列,遞增子序列的長度至少是2。
說明:
給定數組的長度不會超過15。
數組中的整數范圍是 [-100,100]。
給定數組中可能包含重復數字,相等的數字應該被視為遞增的一種情況。
思考
這一題和leetcode 90. 子集 II 思考分析的思想有點像。
但是需要注意的是:
1、該數組是求遞增子序列,所以不能打亂原數組的順序。
2、遞增子序列
3、遞增子序列的長度最少是2
其它的思想:回溯、去重其實和leetcode 90. 子集 II 思考分析是一樣的。
對于上面兩個問題,我們可以這也解決:
1、我們之前排序的是為了使相同的元素靠到一起,然后通過判斷元素是否出現過來去重:
if(i > start && nums[i] == nums[i-1]) continue;
既然是判斷元素是否出現過,那么我們就可以使用哈希法,注意這里判斷的是解空間樹本層是否出現重復元素,所以去重操作仍然是在for循環中:
unordered_set<int> set;
for(int i=start;i<end;i++)
{//如果在本層重復使用了某個元素,那么跳過if(set.find(nums[i])!=set.end()) continue;set.insert(nums[i]);//剩下的回溯代碼}
2、遞增序列如何判斷:
只要在本層for循環中檢查該元素是否大于子序列的最后一個元素即可:
//如果元素小于子序列的最后一個元素
if(res.size()>=1 && nums[i]<res[res.size()-1]) continue;
注意這個continue操作應該在上一個哈希法去重之前。
3、遞增子序列的長度最少是2,在將res送入result之前先進行判斷一下
if(res.size()>=2) result.push_back(res);
至此,我們這個問題就解決差不多了。
下面是整個代碼:
代碼
注意這里的floor是為了調試看層數的,所以可以不使用這個變量。
class Solution {
public:vector<vector<int>> result;vector<int> res;int floor=0;void backtracking(vector<int>& nums,int start,int end){if(res.size()>=2) result.push_back(res);//剩余集合為空,返回if(start>=end){return;}unordered_set<int> set;for(int i=start;i<end;i++){//如果元素小于子序列的最后一個元素if(res.size()>=1 && nums[i]<res[res.size()-1]) continue;//如果在本層重復使用了某個元素if(set.find(nums[i])!=set.end()) continue;set.insert(nums[i]);//cout<<nums[i]<<"層數:"<<floor<<endl;//處理結點;res.push_back(nums[i]);floor++;//遞歸,探索下一層backtracking(nums,i+1,end); //遞歸floor--;//回溯,撤銷處理結果res.pop_back();}return;}vector<vector<int>> findSubsequences(vector<int>& nums) {result.clear();res.clear();floor=0;backtracking(nums,0,nums.size());return result;}
};
優化
對于本層元素是否重復使用我們使用了set,題目中限定了數值范圍[-100,100]所以可以用數組來做哈希表。
因為對set的insert操作需要做哈希映射相對耗費時間,并且每次重新定義set,insert的底層符號表也要做擴充。
class Solution {
public:vector<vector<int>> result;vector<int> res;int floor=0;void backtracking(vector<int>& nums,int start,int end){if(res.size()>=2) result.push_back(res);//剩余集合為空,返回if(start>=end){return;}int usedArray[201]={0}; //這里使用數組來進行去重操作。for(int i=start;i<end;i++){//如果元素小于子序列的最后一個元素if(res.size()>=1 && nums[i]<res[res.size()-1]) continue;//如果在本層重復使用了某個元素if(usedArray[nums[i]+100] ==1) continue;usedArray[nums[i]+100] =1;//cout<<nums[i]<<"層數:"<<floor<<endl;//處理結點;res.push_back(nums[i]);floor++;//遞歸,探索下一層backtracking(nums,i+1,end); //遞歸floor--;//回溯,撤銷處理結果res.pop_back();}return;}vector<vector<int>> findSubsequences(vector<int>& nums) {result.clear();res.clear();floor=0;backtracking(nums,0,nums.size());return result;}
};