8.最长上升子序列 II

 时间复杂度n * log n

加个二分

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 100010;
 4 int a[N]; //存储每一个数
 5 int q[N]; //不同长度的上升子序列结尾的最小值
 6 int main() {
 7     int n;
 8     cin >> n;
 9     for (int i = 0; i < n; i++) {
10         cin >> a[i];
11     }
12     int len = 0; //最大长度,也就是q里面的元素个数
13     //注意:我们要在q数组中二分出来小于某个数的最大的数
14     //为了保证数组当中小于某个数的数一定存在,设置一个哨兵
15     //这个哨兵一定要小于所有数
16     q[0] = -2e9; //这是哨兵
17     for (int i = 0; i < n; i++) {
18         int l = 0, r = len;
19         //在这个范围之间找到小于a[i]的最大的数
20         while (l < r) {
21             int mid = (l + r + 1) / 2;
22             if (q[mid] < a[i]) { //说明我们要找到的答案在mid以及mid右边
23                 l = mid;
24             } else {
25                 r = mid - 1;
26             }
27         }
28         //二分出的l,r就是可以接在哪个长度后面
29         len = max(len, l + 1); //更新最大值
30         q[l + 1] = a[i]; //更新下一个数
31     }
32     cout << len << endl;
33     return 0;
34 }

也可以用库函数来写

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 100010;
 4 int a[N];
 5 int main() {
 6     int n;
 7     cin >> n;
 8     for(int i = 0; i < n; i++) {
 9         cin >> a[i];
10     }
11     vector<int> v;
12     for(int i = 0; i < n; i++) {
13         vector<int>::iterator it = lower_bound(v.begin(), v.end(), a[i]);
14         //lower_bound(val):返回容器中第一个值【大于或等于】val的元素的iterator位置。
15         //upper_bound(val):返回容器中第一个值【大于】val的元素的iterator位置。
16         if (it == v.end()) {
17             v.push_back(a[i]);
18         } else {
19             *it = a[i];
20         }
21         cout << "i: " << i << endl;
22         for (int i = 0; i < v.size(); i++) {
23             cout << v[i] << " ";
24         }
25         cout << endl;
26     }
27     cout << v.size() << endl;
28     return 0;
29 }

 

posted @ 2020-07-03 13:40  kyk333  阅读(167)  评论(0)    收藏  举报