leecode 300. Longest Increasing Subsequence

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4 
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. 

Note:

  • There may be more than one LIS combination, it is only necessary for you to return the length.
  • Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

题目大意:找出无序数组中最长上升子序列的长度, 时间复杂度要求为O(nlgn);

最直接的办法是暴力求解,记录下每个位置的上升序列长度, 当要计算某个位置的上升序列长度的时候,就向前面找到比该值小且上升序列的长度和该位置的上升序列长度差值不超过一的数; 这样做的方法简单,但是会进行很多重复的查询;

改进办法:用一个数组来模拟栈lis,这个数组按照记录出现的升序数字, 当新出现的数字比栈顶的数字大, 则添加到栈中,否则更新数组中的数;  

Input: [10,9,2,5,3,7,101,18]
初始lis={10}
依次遍历数组:出现的是9, 9比栈顶元素小, 查找9应该插入的位置, lis更新为{9}
2: 依旧是更新的操作, {2}
5: 5比栈顶元素大, 添加到栈中, {2, 5};
3: 把3插入到lis中, lis更新为{2, 3}
7: 把7添加到lis中, lis更新为{2,3,7}
101: 把101添加到lis中, 更新为{2,3,7, 101}
18: 插入到lis中, 更新为{2, 3, 7, 18}
可以发现只有在新出现的数字比栈顶元素大的时候,lis的大小才会改变, 其他情况不会改变lis的大小,但会把lis中某一个元素替换掉
如最后一步,把101替换为18, 这样做的意义是什么, 是为了让上升序列更有潜力, 加入数组扩展为 10,9,2,5,3,7,101,18, 50, 90; 如果没有把101替换为18,最长子序列的长度会保持在4, 这显然是错误;
lis中保存的并不是正确的最长上升子序列, 但是其长度和最长上升子序列是相同的;
这里用了stl库中的lower_bounder函数, 函数返回和num相同或者第一个比num大的数的位置, 我们通过这个位置来跟新lis中的元素
 1 class Solution {
 2 public:
 3     int lengthOfLIS(vector<int>& nums) {
 4         if(nums.size()==0) return 0;
 5         auto m=nums.begin();
 6         for(auto num:nums){
 7             auto it=lower_bound(nums.begin(), m, num);
 8             *it=num;
 9             if(it==m) m++;
10         }
11          return m-nums.begin();
12     }
13 };

猜你喜欢

转载自www.cnblogs.com/mr-stn/p/9221051.html