最长上升子序列 - 时间复杂度O(NlogN)

300. 最长递增子序列 - 力扣(LeetCode)

维护一个数组tail,其中,元素tail[k] 表示 长度为k的上升子序列的末尾元素的最小值

数组tail是严格递增的

对任意下标 i < j,tail[i] < “tail[j]所在的序列长度为m的前缀的结尾元素” <= tail[j]
第一个 “<” 是因为 长度为n的上升子序列长度为m的前缀 都是 长度为m的上升子序列
第二个 “<=” 是因为 tail[j]所在的序列 是上升的。

更新lower_bound(tail,nums[n])

已知 nums[0…n-1]的tailnums[n]
nums[n] 追加到 末尾元素小于nums[n]的上升子序列 的后面,产生一组新的上升子序列。
在新的上升子序列中,只有最长的那些可能更新 数组tail
因为,“非最长的序列(设长度为s)的末尾元素nums[n]” > “最长的新序列的长度为s的前缀的结尾元素” >= tail[s]

代码

	int lengthOfLIS(std::vector<int> nums) {
		std::vector<int> tail(nums.size(), INT_MAX);
		for (int i = 0; i < nums.size(); ++i)
			*std::lower_bound(tail.begin(), tail.end(), nums[i]) = nums[i];
		return std::lower_bound(tail.begin(), tail.end(), INT_MAX) - tail.begin();
	}
上一篇:3.31面试pony.ai


下一篇:插入排序、希尔排序(Shell)、选择排序、堆排序、冒泡排序、快速排序、归并排序和基数排序(桶排)的 时间复杂度和空间复杂度