算法题-数组的最长递增子序列

 题目

给定一个无序的数组,返回其中最长递增子序列的长度。

 

解法

利用一个辅助数组1,记录每个长度的LIS的结尾字符,最后其长度就是所求值;

辅助数组2,与1同步变化,记录数组1中每个元素在输入序列中的原始下标;

辅助数组3,与输入数组等长,记录每个元素在一个LIS中的前驱下标。

 

代码

 

 1 int binSearch(const vector<int> &tail, int len, int key)  //辅助函数,二分查找,找出key或者第一个大于key的下标
 2 {
 3     int left = 0, right = len - 1;
 4     int mid;
 5 
 6     while(left <= right)
 7     {
 8         mid = left + ((right - left) >> 1);
 9         if(tail[mid] == key)
10             return mid;
11         else if(tail[mid] > key)
12             right = mid - 1;
13         else
14             left = mid + 1;
15     }
16 
17     return left;  //如果不存在key,则返回第一个大于key的元素下标
18 }
19 
20 void LIS(int *a, int n)
21 {
22     vector<int> tail(n); //辅助数组1,当前每个LIS子序列的结尾字符,递增的
23     vector<int> orig(n); //辅助数组2,与数组1同步变化,当前结尾在原始数组的下标
24     vector<int> prev(n); //辅助数组3,与输入等长,当前结尾字符的上一元素在原始输入中的下标
25     int len = 0;
26 
27     tail[0] = a[0];  //初值
28     orig[0] = 0;
29     prev[0] = -1;
30     ++len;
31 
32     for(int i = 1; i < n; ++i)
33     {
34         if(a[i] > tail[len - 1])  //直接添加在尾部,LIS长度+1
35         {
36             tail[len] = a[i];
37             orig[len] = i;
38             prev[i]   = orig[len - 1];
39                         
40             ++len;
41         }
42         else
43         {
44             int pos = binSearch(tail, len, a[i]);
45             tail[pos] = a[i];  //替换掉一个字符
46             orig[pos] = i;
47             prev[i]   = pos > 0 ? orig[pos - 1] : -1;
48         }
49     }
50 
51     stack<int> stk;  //用栈,因为记录的路径是逆序的
52     for(int cur = orig[len - 1]; cur >= 0; cur = prev[cur])
53     {
54         stk.push(a[cur]);
55     }
56 
57     cout << len << endl;
58     while(!stk.empty())
59     {
60         cout << stk.top() << ' ';
61         stk.pop();
62     }
63     cout << endl;
64 }

 

posted @ 2014-09-27 02:14  阿杰的专栏  阅读(820)  评论(0编辑  收藏  举报