关于这道题,其实就是利用动态规划的一种思想,解这道题有点类似冒泡,采用遍历数组序列,不断更新递增序列的长度以至于来找到最长单调递增序列。
关于问题呢,大概已有有一点思路:
下面将思路画一画,通过将思想的整理,得到这样一副图:
通过图片我们可以看出要想找到最长递增子序列,我们得不断扩大范围这里是指图片中的(sub[i]所对应的区间),其实也就在小区间得到递增的序列的长度,然后继续扩大区间来更序列长度,更新到最大区间时就会找到一个最大的递增子序列。
先画一画然后得出这样的解决方案,然后就是调整代码实现这一过程便是找到最优解的方案。
以下是实现代码:
mian()函数:
#include<iostream>
using namespace std;
#include<vector>
#define MAX(a,b) a>b?a:b
int main()
{
vector<int> LIS;//存储最长子序列
int father[10] = { 6, 7, 5, 6, 7, 8, 9, 10, 1,3 };//n元素的数组
int n = sizeof(father) / sizeof(father[0]);//数组大小
int sub[10] = { 0 };//0到{0,1,2,3,4,5,,,n}区间的子序列长度
getSLIS(father, sub,LIS,n);//获取子序列长度
int lensub = 0;
cout << "以下是每个区间更新得到子序列长度:" << endl;
for (int i = 0; i < n; i++)//遍历sub,找出最大子序列长度
{
cout << sub[i] << " ";//打印更于sub中的子序列长度
lensub = MAX(lensub, sub[i]);//选出最长的子序列
}
cout << endl;
cout << "输出子序列长度:" << endl;
cout << lensub << endl;
cout << "输出子序列:" << endl;
for (size_t i = 0; i < LIS.size(); i++)//输出子序列
{
cout << LIS[i] << " ";
}
cout << endl;
}
核心算法逻辑 getSLIS()函数
void getSLIS(int* f, int* s, vector<int>& LIS, int n)
{
for (int i = 0; i < n; i++)
{
s[i] = 1;//初始化每个子序列长度为1
for (int j = 0; j < i; j++)
{
int k = 0;
if (f[i]>f[j] && s[i] + 1>s[j])//更新条件
{
s[i] = s[j] + 1;//更新
if (s[i] > LIS.size())
{
LIS.resize(s[i]);
int length = s[i];
int index = i;
while (length)//从当前子序列最大元素倒着将子序列输入LIS,length控制输入长度
{
LIS[length - 1] = f[index];
length--;
index--;
}
}
}
}
}
}
这里我为了使整个过程看起来更明了,打印了很多东西,为了清楚的看到最长递增子序列还特意使用了vector来辅助完成,这样是代码看起来就有了不少不必要的代码,下面将核心的getSLIS()函数简洁的写出来:
void getSLIS(int* f, int* s, vector<int>& LIS, int n)
{
for (int i = 0; i < n; i++)
{
s[i] = 1;//初始化每个子序列长度为1
for (int j = 0; j < i; j++)
{
int k = 0;
if (f[i]>f[j] && s[i] + 1>s[j])//更新条件
{
s[i] = s[j] + 1;//更新
}
}
}
}