491.遞增子序列
阿新 • • 發佈:2021-06-16
491.遞增子序列
題目
給定一個整型陣列, 你的任務是找到所有該陣列的遞增子序列,遞增子序列的長度至少是 2 。
示例:
輸入:[4, 6, 7, 7]
輸出:[[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
提示:
給定陣列的長度不會超過15。
陣列中的整數範圍是[-100,100]。
給定陣列中可能包含重複數字,相等的數
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/increasing-subsequences
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
題解
思路
題目說的找到所有該陣列的遞增子序列,這裡找的是子序列,其實我不太理解子序列這種具體的說法。
試了兩個示例之後,感覺是序列是有序的?然後子序列元素的前後順序和之前的數組裡元素的前後順序是一致的。
可以發現[4,7,6,7]和[4,6,7,7]的答案是不一樣的,那麼90題先對原陣列排序再去重的思路是沒辦法用的。
按照之前做題的思路,有兩個辦法判斷是否重複
第一個用hash表,第二個是這道題給正數的範圍,那麼可以使用陣列長度為200的陣列arr代表[-100,100]。
如果當前元素是5,那麼arr[5+100] = 1
題解
遞迴的引數和返回值
陣列中的元素不能重複取值,那麼還是需要startIndex來標識取值區間。
List<List<Integer>> res = new ArrayList<>();
List<Integer> path;
void backtracing(int [] nums,int startIndex);
遞迴的終止條件
if(startIndex == nums.length)return; //和之前的題一樣可以省略
單層遞迴邏輯
首先先判斷當前的元素是否之前已經取過,如果取過了,則跳過。
如果沒取過,判斷當前元素是否比path路徑的最後一個元素大,如果大取值並且加入path,否則跳過當前值。
int [] arr = new int[201]//僅供本層使用,每次向下走的時候先為這層新建一個分支 for(int i = startIndex;i<nums.length;i++){//橫向遍歷 if(path.size()>=2) res.add(new ArrayList(path)); if(arr[nums[i]+100]==1) continue; //判斷是否已經取值避免本層重複取值 if( path.size()>0 && nums[i] < path.get( path.size()-1))continue; //這是當前元素比path之前的最後一個元素小,pLen>0裡面有數可以比較。 //這下面都是符合條件的了 arr[nums[i]+100]=1; //這是符合條件設定為1,不符合條件是肯定不是進來的 path.add(nums[i]); backtracing(nums,i+1); path.remove(path.size()-1); //這裡的回溯是為了取下一個分支,因為不符合條件的並不會進來 }
程式碼
class Solution {
List<List<Integer>> res;
List<Integer> path;
public List<List<Integer>> findSubsequences(int[] nums) {
res = new ArrayList<>();
if(nums.length==0) return res;
path = new ArrayList<>();
backtracing(nums,0);
return res;
}
void backtracing(int [] nums,int startIndex){
if(path.size()>=2) res.add(new ArrayList(path));
int [] arr = new int[201];
for(int i = startIndex;i<nums.length;i++){
if(arr[nums[i]+100]==1) continue;
if(path.size()>0 && nums[i] < path.get( path.size()-1))continue;
path.add(nums[i]);
arr[nums[i]+100]=1;
backtracing(nums,i+1);
path.remove(path.size()-1);
}
}
}