问题描述:设L=<a1,a2,…,an>是长度为n的序列,L的递增子序列是这样一个子序列la=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值。
解决方法:动态规划方法。设f(i)表示L中以ai为末元素的最长递增子序列的长度。则有递推公式,
此时时间复杂度为O(n2),若对,max操作进行优化,则可降低到O(nlogn)。
代码实现:
#include <iostream>
template<typename T> int LongestAscendingSequence(T *, const int size);
using namespace std;
int main(void)
{
const int SIZE = 30;
int arr[SIZE] = {1,1,9,9,6,6,8,8,4,4,0,0,7,7,5,5,2,2,3,3,1,9,6,8,4,0,7,5,2,3};
int len_max = 0;
len_max = LongestAscendingSequence(arr, SIZE);
cout << len_max << endl;
return 0;
}
template<typename T> void LASPrint(T *arr, int *pre, int pos)
{
for (; pos >= 0; pos = pre[pos])
{
cout << arr[pos] << ' ';
}
cout << endl;
return;
}
template<typename T> int LongestAscendingSequence(T *arr, const int size)
{
if (size < 0)
{
return 0;
}
int *las_pos = new int[size+1];
int *pre = new int[size+1];
bool *pos_max = new bool[size+1];
las_pos[0] = -1;las_pos[1] = 0;
*pre = -1;
*pos_max = true;
int len_max = 1;
for (int f = 1, m, r, i = 1; i <size; ++i)
{
*(pre + i) = -1;
*(pos_max + i) = false;
f = 1, r = len_max;
while (f <= r)
{
m = (f + r)/2;
if (arr[las_pos[m]] < arr[i])
{
f = m + 1;
}
else
{
r = m - 1;
}
}
las_pos[f] = i;
*(pre + i) = las_pos[f - 1];
if (f > len_max)
{
++len_max;
*(pos_max + i) = true;
}
}
for (int i = 0; i < size; ++i)
{
if(*(pos_max + i))
{
LASPrint(arr, pre, i);
}
}
for (int i = 1; i <= len_max; ++i)
{
LASPrint(arr, pre, las_pos[i]);
}
delete[] pos_max;
delete[] pre;
delete[] las_pos;
return len_max;
}