编程之美之最长递增子序列实现

本文介绍了一种求解最长递增子序列问题的有效算法,采用动态规划结合二分搜索的方法,实现时间复杂度为O(nlogn)。通过实例展示了如何利用数组记录递增子序列的状态,并逐步迭代优化子序列的长度。
// 编程之美之最长递增子序列.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <algorithm>

using namespace std;
#define N 8

#define MAXN 1003
int A[MAXN];
int MaxV[MAXN];

// 动态规划算法O(nlogn)
/*int _tmain(int argc, _TCHAR* argv[])
{
	int n, i, j, k;
	cin >> n;
	for (i=1; i<=n; i++)
		cin >> A[i];
	MaxV[1] = A[1];
	int nmaxv = 1;	// 目前找到的最长递增子序列的长度
	// 有n个阶段,每个阶段有1个状态
	for (i=2; i<=n; i++)
	{
		// 每个状态有nmaxv种决策,以得出以元素i结尾的最长递归子序列的长度
		int u = 1, v = nmaxv;
		while (u<=v)
		{
			int mid = (u+v)>>1;
			if (MaxV[mid] < A[i])
				u = mid+1;
			else
				v = mid-1;
		}

		// 每个元素都会对数组MaxV中的某个元素产生影响
		// 使用二分搜索确定其在第v+1个位置
		nmaxv = max(nmaxv, v+1);
		MaxV[v+1] = A[i];
	}
	cout << nmaxv;
	system("pause");
	return 0;
}*/
int _tmain(int argc, _TCHAR* argv[])
{
	int n, i, j, k;
	int *arr = new int[N];
	int *lengest_min = new int[N+1];//lengest_min[i]表示长度为i的所有子序列中,满足arr[i]最小的子序列,及最后一个值是最小的子序列,lengest_min[i]就是最小子序列的最后的值(最大值)
	for (i=0; i<N; i++)
	{
		cin >> arr[i];
		//cout<<" next "<<endl;
	}
	//cout<<" start "<<endl;
	lengest_min[1]=arr[0];//第一个元素的最小子序列长度为一,最后一个元素是arr【0】
	int minmax=1;
	for(int i=1;i<=N;i++)
	{
		int low=1,mid,high;
		high = minmax;//minmax 是lengest_min[]数组的最大值,
//寻找arr[i]的位置,寻找那些lengest_min[j]的值小于arr[i]的点,若lengest_min[j]的值小于arr[i],说明该子序列可以更长一点,该子序列的最后的值也应更大一点
// 即在lengest_min[] 的数组里找小于arr【i】的元素,因为lengest_min[]有序(迭代的过程要维持有序),所以用二分查找
		while(low<=high)
		{
			mid=(low+high)/2;
			if(lengest_min[mid]<arr[i])
				low=mid+1;
			else high=mid-1;
		}// 结束时确实插入位置在high+1处
		//cout<<"high +1 is "<<high+1<<endl;
		if(minmax<high+1) minmax=high+1;
		lengest_min[high+1]=arr[i];//更新lengest-min【】
		//cout<<" lengestmin is "<<lengest_min[high+1]<<endl;
	}
	cout<<" is "<<minmax;
	system("pause");
	return 0;
}

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值