求数组中最长递增子序列(编程之美2.16)

#ifndef _LGONGEST_INCREMENTAL_SEQUENCE_H_ 
#define _LGONGEST_INCREMENTAL_SEQUENCE_H_

#include <vector>
#include <algorithm>
using namespace std;

//编程之美2.16
//最长递增子序列,使用动态规划的时间复杂度为O(n^2).
//但是通过剪枝可以大大减少比较的次数。

//主要思想是:
//1.可以使用一个结构来记录一个长度串中的末位信息,而不是一个元素对应一个长度信息。
//	这样,长度串跟元素是一对多的关系。
//	如果LIS[i]有多个序列,比如如果LIS[2]的序列可能是-1,2和1,10
//	那么对于序列中的下一个值3,4,5,6,12来说,它们都能使用-1,2来构成更长的串,
//	所以LIS[i]应该是长度为i的串中末尾数字的最小值
//2.应该看到,如果i<j,那么LIS[i]<LIS[j],为什么这么说呢?因为如果LIS[i] >= LIS[j]
//	的话,我们就可以把LIS[j]放入到LIS[i]的末尾,从而LIS[j] == LIS[i]矛盾了。

template<typename T>
struct longest_incremental_sequence_comparator
{
	const bool operator()(const T& t1, const T& t2) const
	{
		return t1 < t2;
	}
};

template<typename T>
size_t longest_incremental_sequence(const vector<T>& array)
{	
	vector<T> LIS;
	LIS.reserve(array.size());
	longest_incremental_sequence_comparator<T> c;
	for (size_t i = 0; i != array.size(); i++)
	{//
		const T& t = array[i];

		//由于是有序的,所以使用upper_bound找到第一个比它小的
		vector<T>::iterator itr = upper_bound(LIS.begin(), LIS.end(), t, c);

		if (itr == LIS.end())
		{//最长子序列增加了
			LIS.push_back(t);
		}
		else
		{//更新它的下一个
			if (*itr > t)
			{//
				*itr = t;
			}
		}
	}

	return LIS.size();
}

void test_longest_incremental_sequence()
{
	int arr[] = {1,-1,2,-3,4,-5,6,7};
	vector<int> a(arr, arr+sizeof(arr)/sizeof(arr[0]));
	size_t max_length = longest_incremental_sequence(a);
	cout << max_length << endl;
}

#endif




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值