#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
求数组中最长递增子序列(编程之美2.16)
最新推荐文章于 2022-04-11 09:17:51 发布