看了很多博客,都只是介绍了如何去找最大的长度,而没有介绍如果去存取这个路径,问了实验室的学长,学长说他也不会,开始的时候,我以为模拟的栈中的元素存的就是最长子序列,其实不然,在搜索替换的过程中,为了保证尽量的增加后续的潜力,就尽量的把前面的序列在原有的长度上变下,所以我就会去找到第一个比当前数大的元素,然后替换掉,但是在这里替换就会发现一个问题是,当前元素可能会排到之前元素的前面,所以导致顺序颠倒,所以我们这里需要记住每一个元素曾经出现在最长子序列中的位置,然后我们反向查找,第一个遇到的就是真正LIS中的元素。
sequence : -7 10 9 2 3 8 8 1 temp LIS : position : sequence :(-7)10 9 2 3 8 8 1 temp LIS : -7 position : 1 // -7 在 LIS 的第一個位置 sequence : -7(10) 9 2 3 8 8 1 temp LIS : -7 10 position : 1 2 // 10 在 LIS 的第二個位置,以此類推。 sequence : -7 10 (9) 2 3 8 8 1 temp LIS : -7 9 position : 1 2 2 /* 9 成為 LIS 的潛力比 10 大, 所以以 9 代替 10 */ sequence : -7 10 9 (2) 3 8 8 1 temp LIS : -7 2 position : 1 2 2 2 /* 2 成為 LIS 的潛力比 9 大, 所以以 2 代替 9 */ sequence : -7 10 9 2 (3) 8 8 1 temp LIS : -7 2 3 position : 1 2 2 2 3 sequence : -7 10 9 2 3 (8) 8 1 temp LIS : -7 2 3 8 position : 1 2 2 2 3 4 sequence : -7 10 9 2 3 8 (8) 1 temp LIS : -7 2 3 8 position : 1 2 2 2 3 4 4 /* 8 成為 LIS 的潛力比 8 大, 所以以 8 代替 8 */ sequence : -7 10 9 2 3 8 8 (1) temp LIS : -7 1 3 8 position : 1 2 2 2 3 4 4 2 /* 1 成為 LIS 的潛力比 2 大, 所以以 1 代替 2 */
因為 LIS 長度為 4 ,所以就先找位置為 4 的我的代码如下:sequence : -7 10 9 2 3 8 (8) 1 position : 1 2 2 2 3 4 (4) 2 LIS : - - - 8 /* search 4th, 8 is fourth LIS element */ sequence : -7 10 9 2 (3) 8 8 1 position : 1 2 2 2 (3) 4 4 2 LIS : - - 3 8 /* search 3rd, 3 is third LIS element */ sequence : -7 10 9 (2) 3 8 8 1 position : 1 2 2 (2) 3 4 4 2 LIS : - 2 3 8 /* search 2nd, 2 is second LIS element */ sequence :(-7)10 9 2 3 8 8 1 position : (1) 2 2 2 3 4 4 2 LIS : -7 2 3 8 /* search 1st, -7 is first LIS element */
#include <iostream> #define SIZE 1001 using namespace std; int main() { int a[1001]; int f[1000]; int lis[1000]; int i, j, n, top, temp; int stack[SIZE]; cin >> n; top = 0; /* 第一个元素可能为0 */ stack[0] = -1; for (i = 0; i < n; i++) { cin >> a[i]; temp=a[i]; /* 比栈顶元素大数就入栈 */ if (temp > stack[top]) { stack[++top] = temp; f[i]=top; } 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; f[i]=low; } } /* 最长序列数就是栈的大小 */ cout << top << endl; int t=top; for(int i=n;i>=0;i--) { if(f[i]==t) { lis[--t]=a[i]; } if(t<0) break; } for(int i=0;i<top;i++) cout<<lis[i]<<endl; return 0; }
【LIS】O(nlogn)二分法搜索+路径输出
最新推荐文章于 2023-05-22 20:27:10 发布