C语言怎么求一维数组的最长上升子序列?

题目:最长上升子序列的长度
如:1 4 -3 -9 5 9 0 //1 4 5 9
如:1,5,2,3,4,6,-5,-9,10,11// 1 2 3 4 6 10 11
子序列 不要求连续,前后关系要和原序列一致

最长递增子序列是非常经典的一个算法问题。看到题目时需注意子序列和子串是并不相同的,子串必须是连续的。所以第一时间想到的也是最无脑的方法----穷举法,似乎不能用了。真的不能用吗?可以,不过需要一些变通。

穷举法

穷举法就是把所有可能出现的情况一个一个例举出来再进行判断。在这题中单纯的循环遍历数组是行不通的,那只能求出最长上升子串。而我们知道子序列是数组的一个子集,那我们例举出该数组所有的子集不就可以了。那么怎么例举的呢?这就需要我们引入一个概念位运算。我们都知道数据存储在计算机中只有两种形式 0 或者 1 ,而我们以 0 或者 1 来指代这个数组的子集中是否含有该元素,0 和 1 所在的位置指代该元素在数组中的位置,然后再进行遍历判断该序列是否为上升序列就行了。

话不多说上代码

#include<stdio.h>
int main()
{
	int i,j,t1,t2,n,N;
	printf("请输入数组的长度:\n");
	scanf("%d",&N);
	int a[N];  //这里有些编译器不支持这种写法,直接将值固定就行。
	for (i =0; i < N; i++)
		scanf("%d",&a[i]);
	
	int max = 1;//存储最长上升子序列的长度
	for(j = 1 ; j < (1 <<N); j++ )
	{
		t1 = t2 = -65535;
		//t1 保存当前选中的元素的值
		//t2 保存上一个选中的元素的值
		n = 0; //上升序列的元素个数
		for(i = 0; i <N; i++)
		{
			if(j & (1 << i))   //判断是否有第 i 位元素
			{
				t2 = t1;
				t1 = a[i];
				if(t1 > t2)  
				{
					n ++;
					if(n > max)
					{
						max = n;
					}
				}
				else 
				{
					break;
				}
			}
		}
	}
	printf("最长上升序列的长度为%d\n",max);
}

但是这种方法的时间复杂度非常高(2N),并且只能判断32位数以下的数组-----int 类型只含有32位。
所以并不推荐使用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值