实验名称
分析题3-2 单调递增最长子序列问题。
实验目的
分析题3-2 单调递增最长子序列问题。
实验原理
动态规划+二分查找。array是原数组,B中存储我们在考察序列时的值,len用来记录B数组中个数。
实验步骤
①用array[0]初始化辅助数组B[0],len=1,活动列表添加array[0]。
②添加后面的元素。
若小于当前活动列表中所有活动序列最末尾的元素,则创建一个长度为1的新的活动序列,并删除其他等长的活动序列。
若大于所有活动序列最末尾的元素,相应的array和B数组最末尾的元素比较大小即可判断,直接在B中添加元素。
若在两者之间,使用二分查找法,确定位置之后替换比它大的元素。
时间复杂度分析
O(nlogn)。
实验心得
通过这次实验,我回顾了动态规划和二分查找的知识。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <windows.h>
#include <iostream>
#include <ctime>
using namespace std;
int len;
int BiSearch(int *b, int len, int w)
{
int left = 0, right = len - 1;
int mid;
while (left <= right)
{
mid = left + (right-left)/2;
if (b[mid] > w)
right = mid - 1;
else if (b[mid] < w)
left = mid + 1;
else //找到了该元素,则直接返回
return mid;
}
return left;//数组b中不存在该元素,则返回该元素应该插入的位置
}
int LIS(int *array, int n)
{
int len;
int B[n];
len = 1;
B[0] = array[0];
int i, pos = 0;
for(i=1; i<n; ++i)
{
if(array[i] > B[len-1]) //如果大于B中最大的元素,则直接插入到B数组末尾
{
B[len] = array[i];
++len;
}
else
{
pos = BiSearch(B, len, array[i]); //二分查找需要插入的位置
B[pos] = array[i];
}
}
printf("LIS: %d\n", len);
}
int main()
{
ifstream in;
in.open("input.txt");
ofstream out;
int N;
in>>N;
int B[N];
int array[N];
for(int i=0;i<N;i++)
{
in>>array[i];
}
in.close();
clock_t start,end;
start=clock();
LIS(array,N);
end=clock();
printf("时间:%fms\n",(double)(end-start)/CLK_TCK);
return 0;
}
#include<stdlib.h>
#include<time.h>
#include<fstream>
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
ofstream out("input.txt");
out<<n<<'\n';
srand((unsigned)time(NULL));
for(int i=0;i<n;i++)
{
out<<rand()<<' ';
if((i+1)%10==0) out<<'\n';
}
out.close();
return 0;
}