|
/** * MaxOrderedSubsequence.cpp * @Author Tu Yongce <yongce (at) 126 (dot) com> * @Created 2008-4-26 * @Modified 2008-4-26 * @Version 0.1 */
#include <iostream> #include <vector> #include <iterator> #include <algorithm>
using namespace std;
/* * 计算最长有序子序列(子序列不必连续) * note: 算法时间复杂度为O(nlgn),空间复杂度也为O(n) */ template <typename T> struct ArrayIndexCompare { const T *arr_;
ArrayIndexCompare(const T *arr): arr_(arr) { }
bool operator() (int lhs, int rhs) const { return arr_[lhs] < arr_[rhs]; } };
template <typename T> void MaxOrderedSubsequence(const T arr[], size_t num, vector<int> &subseqIndices) { vector<int> m; vector<int> pre(num, -1);
m.push_back(-1); // 哨兵 for (int i = 0; static_cast<size_t>(i) < num; ++i) { // 二分搜索 vector<int>::iterator it = upper_bound(m.begin() + 1, m.end(), i, ArrayIndexCompare<T>(arr)); --it; // 在数组m中二分查找元素m[j],使arr[m[j]] ≤ arr[i]且j最大 pre[i] = *it; // 记下arr[i]的前驱元素下标
if (it == m.end() - 1) m.push_back(i); // 比m中对应的元素都大,当前最大子序列增长 else if (arr[i] < arr[*++it]) *it = i; // 长为j + 1的最大子序列的最大值有更小值,需要更新 } // 将最大有序子序列的数组下标输出 subseqIndices.resize(m.size() - 1); int indexIn = m[m.size() - 1]; int indexOut = subseqIndices.size() - 1; while (indexOut >= 0) { subseqIndices[indexOut--] = indexIn; indexIn = pre[indexIn]; } }
void MaxOrderedSubSequenceTest() { // 示例1 //int arr[] = {1, 7, 3, 5, 9, 4, 8}; int arr[] = {3, 7, 1, 5, 9, 3}; const size_t NUM = sizeof(arr) / sizeof(arr[0]);
vector<int> subseq; MaxOrderedSubsequence(arr, NUM, subseq);
cout << "序列:"; copy(arr, arr + NUM, ostream_iterator<int>(cout, " ")); cout << "\n最长有序子序列长度为:" << subseq.size(); cout << "\n最长有序子序列下标为:"; copy(subseq.begin(), subseq.end(), ostream_iterator<int>(cout, " ")); cout << "\n最长有序子序列为:";
for (size_t i = 0; i < subseq.size(); ++i) cout << arr[subseq[i]] << ' '; cout << endl;
// 示例2 char arr2[] = {'D', 'A', 'E', 'K', 'T', 'Q', 'H'}; const size_t NUM2 = sizeof(arr2) / sizeof(arr2[0]); MaxOrderedSubsequence(arr2, NUM2, subseq);
cout << "\n序列:"; copy(arr2, arr2 + NUM2, ostream_iterator<char>(cout, " ")); cout << "\n最长有序子序列长度为:" << subseq.size(); cout << "\n最长有序子序列下标为:"; copy(subseq.begin(), subseq.end(), ostream_iterator<int>(cout, " ")); cout << "\n最长有序子序列为:";
for (size_t i = 0; i < subseq.size(); ++i) cout << arr2[subseq[i]] << ' '; cout << endl; }
|