给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是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]]
题解(一):利用回溯法找到数组所有的子序列,然后判断该子序列是否是递增序列,同时也要维护一个哈希表用于去重
class Solution {
/*
* res用于存储最终结果
* stack用于实现回溯算法
* check用于去重
*/
List<List<Integer>> res=new ArrayList<>();
Stack<Integer>stack=new Stack<>();
HashSet<ArrayList<Integer>>check=new HashSet<>();
public List<List<Integer>> findSubsequences(int[] nums) {
for(int i=0;i<nums.length;i++){
stack.push(nums[i]);
DFS(nums,i);
stack.pop();
}
return res;
}
private void DFS(int[] nums,int index){
for(int i=index+1;i<nums.length;i++){
if(nums[i]>=stack.peek()){
stack.push(nums[i]);
ArrayList<Integer>subRes=new ArrayList<>();
for(int x:stack)
subRes.add(x);
if(!check.contains(subRes)) {
check.add(subRes);
res.add(subRes);
}
DFS(nums,i);
stack.pop();
}
}
}
}
题解(二):利用二进制枚举法同样可以找到数组所有的子序列
class Solution {
public List<List<Integer>> findSubsequences(int[] nums) {
List<List<Integer>>res=new LinkedList<>();
Set<List<Integer>>check=new HashSet<>();
int len= nums.length;
/*
* 子序列一共有(1<<len)种情况,区间[0,1<<len)中的每一个整数转换
* 为二进制数后都代表一个子序列,若该二进制数的某一位为1,则取下标与其
* 对应的数组数字,若为0,则不取
*/
for(int i=1;i<=(1<<len);i++){
List<Integer>temp=getSubSequences(nums,i);
if(temp!=null&&temp.size()>=2&&!check.contains(temp)){
res.add(temp);
check.add(temp);
}
}
return res;
}
private List<Integer>getSubSequences(int []nums,int order){
List<Integer>subSequence=new ArrayList<>();
int index=0;
while(order>0){
/*
* 找出数字order转换为二进制数字后1出现的位置,
* 然后将该位置对应下标的数组数字加入序列
*/
if((order&1)==1){
int len=subSequence.size();
if(subSequence.isEmpty()||nums[index]>=subSequence.get(len-1))
subSequence.add(nums[index]);
else return null;
}
order>>=1;
index++;
}
return subSequence;
}
}