最长上升子序列问题LIS
2016-08-09 20:45
267 查看
问题描述(poj2533):对于给定的n个整数A1, A2…An, 从左到右的顺序选择尽可能多的数,组成一个上升子序列。(上升子序列可以理解为:删除0个或多个数, 其他数的顺序不变, 例如1, 6, 2, 3, 7, 5, 可以选出上升子序列1, 2, 3, 5 也可以选出 1, 6, 7)
poj2533 : 求最长上升子序列的长度
法一:通过DP记忆化搜索求解问题,时间复杂度为O(n^2)
法二:用DP二分搜索解决问题降低时间复杂度,该方法的时间复杂度为O(nlogn)
实现:开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。
举例:原序列为1,5,8,3,6,7
栈为1,5,8,此时读到3,用3替换5,得到1,3,8; 再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。
如果想要输出最长有序子数列的话,可以在法二的基础上稍作改动。
用一个b【i】记录第i个元素在队列中的位置,然后逆向寻找,依次输出。
poj2533 : 求最长上升子序列的长度
法一:通过DP记忆化搜索求解问题,时间复杂度为O(n^2)
#include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #include<string> #include <algorithm> using namespace std; int n, m, i, j, mx; const int maxn = 1010; int a[maxn], d[maxn]; //记忆化搜索 //状态:d[i]:第i个数的最长子序列的长度 //状态转移为d[i] = max(d[i], d[j] + 1); int main() { while(~scanf("%d",&n)){ //共有n个数 for(i = 0; i < n;i++) //录入n个数保存在数组a[]中 scanf("%d",&a[i]); for (i = 0; i < n; i++) { d[i] = 1; //初始化数组d[]为1, for(j = 0;j < i;j++) if(a[j] < a[i]) d[i] = max(d[i], d[j] + 1); //第i个数的最长子序列长度 等于 比 第i个数小 的 数的最长子序列加1 } mx = 0; for(i = 0;i < n;i++) mx = max (mx ,d[i]); printf("%d\n",mx); } return 0; }
法二:用DP二分搜索解决问题降低时间复杂度,该方法的时间复杂度为O(nlogn)
实现:开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。
举例:原序列为1,5,8,3,6,7
栈为1,5,8,此时读到3,用3替换5,得到1,3,8; 再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。
如果想要输出最长有序子数列的话,可以在法二的基础上稍作改动。
用一个b【i】记录第i个元素在队列中的位置,然后逆向寻找,依次输出。
//二分搜索 #include <iostream> #define SIZE 1001 using namespace std; int main() { int i, j, n, top, temp; int stack[SIZE]; cin >> n; top = 0; stack[0] = -1;//令栈顶元素为-1 for (i = 0; i < n; i++) { cin >> temp; /* 比栈顶元素大数就入栈 */ if (temp > stack[top]) { stack[++top] = temp; } else { int low = 1, high = top; int mid; /* 二分检索栈中比temp大的第一个数 */ while (low <= high) { mid = (low + high) / 2; if (temp > stack[mid]) { low = mid + 1; } else { high = mid - 1; } } /* 用temp替换 */ stack[low] = temp; } } /* 最长序列数就是栈的大小 */ cout << top << endl; //system("pause"); return 0; }
相关文章推荐
- 最长上升子序列问题 (LIS)
- LIS 最长上升子序列问题 nlgn时间打印其中一个序列
- hdu 5421 小明系列问题——小明序列(LIS最长上升子序列)
- POJ - 3903 Stock Exchange(LIS最长上升子序列问题)
- LIS求解最长上升子序列问题
- Stock Exchange(LIS最长上升子序列问题)
- LIS 最长严格上升子序列问题
- 最长上升子序列(LIS)问题
- Longest Increasing Subsequence[LIS 最长上升子序列问题] (Longest Ordered Subsequence) POJ - 2533 队列优化
- Leetcod-300_最长上升子序列LIS-基础动态规划问题-【C++】
- 最经典的最长上升子序列问题【LIS】【垃圾死啦都】
- 关于最长上升子序列的问题(LIS)
- lis求最长上升子序列问题
- 动态规划-最长上升子序列(LIS)
- 最长上升子序列问题--题解
- LIS 最长单调上升子序列
- LIS 最长上升子序列N^2以及nlogn算法
- 最长上升子序列问题的几种解法
- poj 2533 Longest Ordered Subsequence(LIS(最长上升子序列))
- 动态规划-最长上升子序列(LIS)