整数配列が与えられた場合、あなたの仕事は配列のすべての増加するサブシーケンスを見つけることであり、増加するサブシーケンスの長さは少なくとも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]]
問題の解決策(1):バックトラッキングメソッドを使用して配列のすべてのサブシーケンスを検索し、サブシーケンスが増加シーケンスであるかどうかを判断し、重複排除用のハッシュテーブルを維持する
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();
}
}
}
}
問題の解決策(2):バイナリ列挙を使用すると、配列のすべてのサブシーケンスも検索できます
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;
}
}