leetcode 491递增子序列[1]

本文深入探讨了LeetCode上递增子序列问题的解决策略,通过递归方法寻找数组中所有长度至少为2的递增子序列。文章详细解释了如何避免重复解,以及如何利用set数据结构进行优化。此外,还介绍了最长递增子序列的求解方法,包括递推方程的定义和实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述: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]]

说明:

  1. 给定数组的长度不会超过15。
  2. 数组中的整数范围是 [-100,100]。
  3. 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。   

思路:递归求解,找下一个大于当前元素的。

注意使用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]);            
  }

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值