贪心+二分:tails 数组维护各长度子序列的最小结尾,lower_bound 更新保证严格递增。
OJ: leetcodecn
题目 ID: longest-increasing-subsequence
难度:普及+/提高
标签:动态规划二分查找贪心
日期: 2026-07-29 12:45
题意
求数组的最长严格递增子序列长度。
思路
维护 tails 数组:tails[k] 表示长度为 k+1 的递增子序列的最小结尾元素。对每个 x,用 lower_bound 找到 tails 中第一个 x 大于所有 tails,则追加。
严格递增用 lower_bound(upper_bound(
代码
cpp
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int lengthOfLIS(vector<int> &nums) {
vector<int> tails;
for (int x : nums) {
auto it = lower_bound(tails.begin(), tails.end(), x);
if (it == tails.end())
tails.push_back(x);
else
*it = x;
}
return tails.size();
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int &x : a)
cin >> x;
cout << Solution().lengthOfLIS(a) << '\n';
return 0;
}python
#!/usr/bin/env python3
import bisect
from typing import List
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
tails = []
for x in nums:
i = bisect.bisect_left(tails, x)
if i == len(tails):
tails.append(x)
else:
tails[i] = x
return len(tails)
def main():
n = int(input())
a = list(map(int, input().split()))
print(Solution().lengthOfLIS(a))
if __name__ == "__main__":
main()复杂度
- 时间复杂度:
。 - 空间复杂度:
。
总结
LIS 的 tails 数组维护的是"各长度最优结尾",lower_bound 更新保证严格递增。tails 的长度即为答案,但 tails 本身不一定是合法的子序列。