题目描述:https://leetcode-cn.com/problems/increasing-subsequences/description/
给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是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]。
- 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。
思路:递归求解,找下一个大于当前元素的。
注意使用set来排除重复!
另外,可以看看最长递增子序列的求法
对于题目的错误理解,让我花费了快4个小时!
class Solution {
public:
vector<vector<int>> res;
set<vector<int>> jihe,jihe2;
int b[15];
int NN;
/*
void process(vector<vector<int>> &res,vector<int>& anums)
{
int Num=anums.size();
int allNum=1<<Num,k;
for(int i=0;i<Num;i++)
cout<<anums[i]<<" ";
cout<<endl;
for(int i=1;i<allNum;i++)
{
k=i;
int j=0;
vector<int> vi;
while(k)
{
if(k%2==1) vi.push_back(anums[j]);
k=k/2;
j++;
}
if(jihe.count(vi)==0&&vi.size()>1)
{
jihe.insert(vi);
res.push_back(vi);
}
}
} //这些代码没有使用,可以用来列举一个集合的子集
*/
void dfs(int x,int index,int level,vector<int>& nums) {
if(index<NN) b[level]=x;
int i=0;
for(i=index+1; i<NN; i++) {
if(nums[i]>=x)
dfs(nums[i],i,level+1,nums);
}
vector<int> temp(b,b+level+1);
if(jihe2.count(temp)==0&&temp.size()>1) {
jihe2.insert(temp);
for(int s=0; s<temp.size(); s++)
cout<<temp[s]<<" ";
cout<<endl;
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
vector<int> temp;
NN=nums.size();
int ib=0,ie=0;
for(int i=0; i<nums.size(); i++) {
dfs(nums[i],i,0,nums);
}
return vector<vector<int>> (jihe2.begin(),jihe2.end());
}
};
可以看看最长递增子序列的求法:
设f(i)表示L中以ai为末元素的最长递增子序列的长度。则有如下的递推方程:
这个递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。
public void lis(float[] L)
{
int n = L.length;
int[] f = new int[n];//用于存放f(i)值;
f[0]=1;//以第a1为末元素的最长递增子序列长度为1;
for(int i = 1;i<n;i++)//循环n-1次
{
f[i]=1;//f[i]的最小值为1;
for(int j=0;j<i;j++)//循环i 次
{
if(L[j]<L[i]&&f[j]>f[i]-1)
f[i]=f[j]+1;//更新f[i]的值。
}
}
System.out.println(f[n-1]);
}