最近楼楼被男朋友带着玩dota,有点上瘾,终于在昨天晚上作出了一个重大的决定,shift+delete删掉warIII文件夹,从此退出dota的明争暗斗。不过最近看男票已经将战场从11转到了topcoder,嗯,这是个好现象,希望楼楼也能跟着玩儿起来。
理想是美好的,唉,可是楼主还在编程之美的初级阶段啊。话不多说了,希望自己加油加油再加油!!(^o^)/~
今天要看的一道题目是求数组中最长递增子序列。
题目简介:
写一个时间复杂度尽可能低的程序,求一个一维数组(N)个元素中的最长递增子序列的长度。例如:在序列1, -1, 2, -3, 4, -5, 6, -7的最长递增子序列的长度为4,这个子序列为1, 2, 4, 6.
注意:题目只要求求长度,不一定要求出这个递增序列。
解法分析:
在这里,要记住一个特别重要的点(对于像楼主这种渣渣),那就是满足无后效性可以使用动态递归来解决。什么叫无后效性,比如1, -1, 2, -3, 4, -5, 6, -7这个序列,当我们找到-1,2,当我们遍历到元素4的时候,只需要比较4和2的关系,如果4比2大,那就可以加进去。而2之前的元素对于我们做决断没有任何影响,这就叫做“无后效性”。所以我们的解法是:
对于前面i个元素的任何一个递增子序列,如果这个子序列的最大元素比array[i+1]小,那么就可以将array[i+1]元素加在这个子序列后面,构成一个新的递增子序列。
详情请见代码,算法复杂度O(N^2),代码中我有非常详细的解释,有什么不明白的,请留言。
#include <iostream>
#include <vector>
using namespace std;
int LIS (int *pArray, int len);
int getMinOfArray (int *pArray, int len);
int main()
{
int a[] = {2, -1, 2, -3, 4, 3, 1, 2, -7, 3, 4, 5, 6, 7, 8, 9};
int len = sizeof(a) / sizeof(int);
vector<int> longestSubSequence;
cout << "最大递增序列的长度为" << LIS(a, len) << endl;
system("pause");
}
int LIS (int *pArray, int len)
{
int *MaxV = new int[len + 1]();
MaxV[1] = pArray[0];
MaxV[0] = getMinOfArray(pArray, len) - 1;
int *LIS = new int[len]();
//初始化最大递增序列的信息
for (int i = 0 ; i < len; i++)
{
LIS[i] = 1;
}
int nMaxLis = 1;
for (int i = 0; i < len; i++)
{
int j;
//下面代码的作用是递归,看有没有比最长递增序列的最大元素的最小值大,如果有的话,那么就可以直接加在后面了。然后最长递增序列的个数加1
//比如,当i = 4, nMaxLis = 2,时,MaxV[2] = 2, a[i] = 4, 4 > 2, 那么4可以加在2后面,递增序列的元素个数加1。找到之后,直接break.
for (j = nMaxLis; j >= 0; j--)
{
if (pArray[i] > MaxV[j])
{
LIS[i] = j + 1;
break;
}
}
//如果i处的最大递增序列,比原来的nMax大的话,那么就更新啦。并且最长递增序列的最大元素的最小值更新为当前元素
if (LIS[i] > nMaxLis)
{
nMaxLis = LIS[i];
MaxV[LIS[i]] = pArray[i];
}
//如果没有比原来的最大长度还长的话,那么就有可能需要更新本长度最大元素的最小值了。比如,nMaxLis = 3的时候,前面我们找到的序列是{1, 2, 4}或者{-1, 2, 4}
//当 i = 5时,j = 2时跳出循环。Lis[5] = 3 <= nMaxLis, 当时3比4小,所以nMaxLis = 3时最大元素的最小值由4更新为3.
else if(MaxV[j] < pArray[i] && pArray[i] < MaxV[j + 1])
{
MaxV[j + 1] = pArray[i];
}
}
delete []MaxV;
delete []LIS;
return nMaxLis;
}
//获取数组元素的最小值
int getMinOfArray(int *pArray, int len)
{
int result = pArray[0];
for (int i = 0; i < len; i++)
{
if (pArray[i] < result)
{
result = pArray[i];
}
}
return result;
}