/* 求解最長遞增子序列長度 */ #include <iostream> #include <limits> using namespace std; //int x[] = {1,-1,2,-3,4,-5,6,-7}; int x[] = {2, 1, 5, 3, 6, 4, 8, 9, 7}; int disp_array(int a[], int len); int find_first_bigger(int a[], int last, int key); int main() { int len = sizeof(x)/sizeof(x[0]); int *z = new int(len + 1); /* z[i] = min(t|t:長度爲i的子序列的最後一個元素) */ z[0] = std::numeric_limits<int>::min(); for (int i = 1; i <= len; ++i) { z[i] = 0; } disp_array(x, len); disp_array(z, len + 1); int t, lislen = 0; for (int i = 0; i < len; ++i) { t = find_first_bigger(z, lislen, x[i]); if (t > lislen) z[++lislen] = x[i]; /* z[]中沒有比x[i]大的*/ else z[t] = x[i]; /* z[t]第一個比x[i] */ } disp_array(z, len + 1); cout << "LIS = " << lislen << endl; return 0; } /** * @brief 在數組a[0..last]中,自左向又查找第一個比key大的數的下標 * 時間複雜度O(lg(n)) * * @param a[] * @param last * @param key * * @return 返回下標,若是沒有比key大的則返回last+1 */ int find_first_bigger(int a[], int last, int key) { int m, p = -1, q = last + 1; /* assume: a[-1] < key <= a[last + 1] */ while (p + 1 != q) { /* invartant: 0 <= p + 1 < q <= last + 1 && a[p] < key <= a[q]*/ m = p + ((q - p)>>1); if (a[m] < key) p = m; else q = m; } return q; } int disp_array(int a[], int len) { for (int i = 0; i < len; ++i) { cout << a[i]; if (i == len -1) cout << endl; else cout << " "; } }