动态规划的思想就是需要在求得最优解的过程中保存中间结果。在求最长不下降子序列的过程中,我们需要保存每个子序列,然后继续往后判断时将当前元素添加到小于该元素并且最长的子序列当中。譬如有序列2、1、3,首先有一个序列2;然后判断1的时候,前面没有比1小的子序列,因此1独自成为一个序列;最后在判断3的时候,前面的两个子序列2和1都比3小,并且这两个子序列的长度也相等,这个时候两个都满足了,我们暂且就保存一个就ok。因此主要的思想总结如下:
1、对于array(n),从第一个元素开始,首先array(1)自成一个子序列,然后我们从array(2)开始往后寻找。
2、判断array(2)将有两种结果:
– 若array(2) >= array(1), 则存在长度为2的不下降子序列array(1),array(2)以及两个长度为1的不下降子序列。;
– 若array(2) < array(1),则存在两个长度为1的不下降子序列array(1)和array(2)。
3、在判断array(i)时,我们在1~i – 1中找出一个比array(i)且最长的子序列中加入array(i)。
对于每个元素i,我们需要记录的是0~i中包括i的最长子序列maxLen[i],以及元素i所对应的前一个元素preIndex[i]。这里preIndex[i]可能可以取多个值,即当前面有多个长度相同的子序列都小于元素i,我们这里值要求取一个即可,如果题目要求输出所有的最长不下降子序列,则需要保存所有了。
两种要求:
只需要求得最长不下降子序列的长度;这时候就不需要保存前驱了;
需要求出最长不下降子序列;就需要保存preIndex[i]了。
[求最长不下降子序列的长度]
#include <iostream>
#include <vector>
using namespace std;
void main()
{
int array[10] = {3, 18, 7, 14, 10, 12, 23, 41, 16, 24};
vector<int> nums(array, array + 10);
vector<int> maxLen(nums.size()); //记录长度
maxLen[0] = 1;
for (int i = 1; i < nums.size(); ++i)
{
int maxL = 0, maxI = -1;
for (int k = i - 1; k >= 0; --k)
{
if(nums[k] > nums[i])
continue;
if(maxLen[k] > maxL)
{
maxL = maxLen[k];
maxI = k;
}
}
maxLen[i] = maxL + 1;
}
int maxL = maxLen[0];
for(i = 1; i < nums.size(); ++i) //找出长度最长的不下降子序列,即maxLen[i]最大的情况
{
if(maxLen[i] > maxL)
maxL = maxLen[i];
}
cout<<maxL<<endl;
}
[求最长不下降子序列]
#include <iostream>
#include <vector>
using namespace std;
void main()
{
int array[10] = {3, 18, 7, 14, 10, 12, 23, 41, 16, 24};
vector<int> nums(array, array + 10);
vector<int> maxLen(nums.size()); //记录长度
vector<int> preIndex(nums.size()); //记录前一元素下标
maxLen[0] = 1, preIndex[0] = -1;
for (int i = 1; i < nums.size(); ++i)
{
int maxL = 0, maxI = -1;
for (int k = i - 1; k >= 0; --k)
{
if(nums[k] > nums[i])
continue;
if(maxLen[k] > maxL)
{
maxL = maxLen[k];
maxI = k;
}
}
maxLen[i] = maxL + 1;
preIndex[i] = maxI;
}
int maxL = maxLen[0], maxI;
for(i = 1; i < nums.size(); ++i) //找出长度最长的不下降子序列,即maxLen[i]最大的情况
{
if(maxLen[i] > maxL)
{
maxL = maxLen[i];
maxI = i;
}
}
do //按照preIndex[]从后往前输出序列
{
cout<<nums[maxI]<<" ";
maxI = preIndex[maxI];
} while (preIndex[maxI] != -1);
cout<<nums[maxI]<<endl;
}