编程题有题号,应该是随机抽取的。
题目大意
给定一个数列,求它的最长上升子序列的长度。
思路 - DP
很简单的 DP ,先做的编程题,就先赶快写了个 O(n2) 的解法便去做前面的题了。设 dp[i]表示以第i 个数为结尾的最长上升子序列的长度,状态转移方程为: dp[i]=max(dp[j])+1,j<i&&num[j]<num[i]
全部做完后,发现还有半个小时,就开始想 O(nlogn) 的解法,虽然已经忘了具体怎么写,但是记得在处理的过程中,以上升子序列的长度为下标,上升子序列的最后一个数为值(长度相同,取较小值),就能构造出一个单调递增的数组,然后就能用二分找到最后一个数小于当前数的最长上升子序列的长度。
熟练后就不需要 dp 数组了
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, num, l, r, mid, mx;
int mn[100003];//mn[i]表示长度为i的上升子序列中,最后一个数的最小值
int main() {
while(1 == scanf("%d", &n)) {
mx = 0;
memset(mn, 0x3f, sizeof(mn));
while(n-- > 0) {
scanf("%d", &num);
l = 1;
r = mx;
while(l <= r) {
mid = (l + r) >> 1;
if(mn[mid] < num) {
l = mid + 1;
}
else {
r = mid - 1;
}
}
mn[r + 1] = min(mn[r + 1], num);
mx = max(mx, r + 1);
}
printf("%d\n", mx);
}
return 0;
}
美团点评还有道读程序题,给了一个Activity的创建和销毁的函数,创建函数中有文件读取,但是没有关闭输入流。只发现了这一个错误。。。