原題:
https://cses.fi/problemset/task/1145
題意:
給長度 n 的序列,求「嚴格遞增」子序列的最長長度。(只需輸出長度)
解題思路:
O(N log N) tails(lower_bound)。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i<n; i++) cin >> a[i];
vector<long long> tails; // tails[len-1] = 長度 len 的最小結尾
tails.reserve(n);
for (int i = 0; i<n; i++) {
long long x = a[i];
// 嚴格遞增 → 找第一個 >= x 的位置
auto it = lower_bound(tails.begin(), tails.end(), x);
if (it == tails.end()) tails.push_back(x);
else *it = x;
}
cout << (int)tails.size() << "\n";
return 0;
}
原題:
https://leetcode.com/problems/longest-increasing-subsequence/description/
題意:
回傳 LIS 長度(嚴格遞增)。
解題思路:
提供兩版:O(N log N) 與 O(N²)。
解法1:O(N log N)(tails)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> tails;
tails.reserve(nums.size());
for (int i = 0; i<nums.size(); i++) {
int x = nums[i];
// 嚴格遞增 → lower_bound
auto it = lower_bound(tails.begin(), tails.end(), x);
if (it == tails.end()) tails.push_back(x);
else *it = x;
}
return tails.size();
}
};
解法2:O(N²)(經典 DP)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
if (n == 0) return 0;
vector<int> dp(n+1, 1);
int best = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
if (dp[j] + 1 > dp[i]) dp[i] = dp[j] + 1;
}
}
if (dp[i] > best) best = dp[i];
}
return best;
}
};