LeetCode 300 最长上升子序列
给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
以下是O(n log n)解法:
[code]class Solution { public: int lengthOfLIS(vector<int>& nums) { int len = nums.size(); if (len < 2) { return len; } vector<int> dp; for (auto& num : nums) { auto idx = lower_bound(dp.begin(), dp.end(), num) - dp.begin(); if (idx >= dp.size()) { dp.emplace_back(num); } else { dp[idx] = num; } } return dp.size(); } };
1. lower_bound 指的是 返回第一个 ”大于等于 value“ 的元素位置。
另一种解释是 可插入”元素值为 value“且 ”不破坏有序性“的第一个位置
2. upper_bound 指的是 返回第一个 “大于 value ” 的元素位置;
另一种解释是 可插入”元素值为 value“且 ”不破坏有序性“的最后一个位置
举个例子: 1 2 2 3 4 5
value = 2: 则 lower_bound 返回的位置是 第 1 个位置;
upper_bound 返回的位置是 第 3 个位置。
大家可以看到一个很有意思的性质:
upper_bound - lower_bound = 数组中 value 的个数
下面我们来研究下 lower_bound 和 upper_bound 的实现。
// return the first element which >= x
int LowerBound(int *a, int n, int x)
{
int left(0), right(n-1), mid;
while(left <= right){
mid = left + ((right - left) >> 1);
if(a[mid] < x){
left = mid + 1;
}
else{
right = mid - 1;
}
}
return left;
}
// return first element which > x
int UpperBound(int *a, int n, int x)
{
int left(0), right(n-1), mid;
while(left <= right){
mid = left + ((right - left) >> 1);
if(a[mid] <= x){
left = mid + 1;
}
else{
right = mid - 1;
}
}
return left;
}
大家知道,在 STL 库中,区间一般采用半闭半开区间 [begin, last),
这种做法的好处是 last - begin 就是区间元素的个数。
以下是 STL 中的源码:
template <class _ForwardIter, class _Tp, class _Distance>
_ForwardIter __lower_bound(_ForwardIter __first, _ForwardIter __last,
const _Tp& __val, _Distance*)
{
_Distance __len = 0;
distance(__first, __last, __len);
_Distance __half;
_ForwardIter __middle;
while (__len > 0) {
__half = __len >> 1;
__middle = __first;
advance(__middle, __half);
if (*__middle < __val) {
__first = __middle;
++__first;
__len = __len - __half - 1;
}
else
__len = __half;
}
return __first;
}
emplace_back:
在容器尾部添加一个元素,这个元素原地构造,不需要触发拷贝构造和转移构造。而且调用形式更加简洁,直接根据参数初始化临时对象的成员。
- 点赞
- 收藏
- 分享
- 文章举报
- Leetcode 300:最长上升子序列
- python【力扣LeetCode算法题库】300 最长上升子序列(动态规划)
- LeetCode300 最长上升子序列
- Leetcode_300_最长上升子序列
- Leetcode 300 Longest Increasing Subsequence 最长递增子序列
- leetcode-300 最长上升子序列 Python
- leetcode 300. 最长上升子序列
- leetcode一题打尽动态规划和贪心算法之300. 最长上升子序列
- leetcode-最长上升子序列
- 【LeetCode 300 Longest Increasing Subsequence】最长递增子序列
- Leetcode 300. 最长上升子序列
- 【手绘漫画】图解LeetCode之最长上升子序列(LeetCode300题),贪心算法 + 二分查找
- Go语言:LeetCode-最长上升子序列
- 300. 最长上升子序列(Longest Increasing Subsequence)
- (Java) LeetCode 300. Longest Increasing Subsequence —— 最长上升子序列
- Leetcod-300_最长上升子序列LIS-基础动态规划问题-【C++】
- LeetCode每日一题——300. 最长上升子序列
- Leetcode 300. 最长上升子序列
- leetcode(300)—— Longest Increasing Subsequence(最长递增子序列)
- 最长上升子序列问题 nlogn 实现算法的简述