算法题-数组的最长递增子序列
题目:
给定一个无序的数组,返回其中最长递增子序列的长度。
解法:
利用一个辅助数组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 }