LeetCode 300. Longest Increasing Subsequence--O(n log n)--Java,C++,Python解法

最长递增子序列O(nlogn)算法解析

题目地址:


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?

这道题目是经典的最长递增子串问题,虽然LeetCode标记为中等难度,我觉得应该是hard难度。

最传统的动态规划的做法是O(N^2)的时间复杂度,我就不提供解法了,着重讲一下O(n log n)的解法。
详细讲解可以看这个网站:最长的子序列大小(N log N) - GeeksforGeeks

Java解法如下:

class Solution {

     public int CeilIndex(int A[], int l, int r, int key) 
    { 
        while (r - l > 1) { 
            int m = l + (r - l) / 2; 
            if (A[m] >= key) 
                r = m; 
            else
                l = m; 
        } 
  
        return r; 
    } 
  
    public int lengthOfLIS(int A[]) 
    { 
        int size=A.length;
        if (size==0) return 0;
        // Add boundary case, when array size is one 
  
        int[] tailTable = new int[size]; 
        int len; // always points empty slot 
  
        tailTable[0] = A[0]; 
        len = 1; 
        for (int i = 1; i < size; i++) { 
            if (A[i] < tailTable[0]) 
                // new smallest value 
                tailTable[0] = A[i]; 
  
            else if (A[i] > tailTable[len - 1]) 
                // A[i] wants to extend largest subsequence 
                tailTable[len++] = A[i]; 
  
            else
                // A[i] wants to be current end candidate of an existing 
                // subsequence. It will replace ceil value in tailTable 
                tailTable[CeilIndex(tailTable, -1, len - 1, A[i])] = A[i]; 
        } 
  
        return len; 
    } 
}

C++解法如下:

class Solution {
public:
   int lengthOfLIS(vector<int>& nums) {
    vector<int> res;
    for(int i=0; i<nums.size(); i++) {
        auto it = std::lower_bound(res.begin(), res.end(), nums[i]);
        if(it==res.end()) res.push_back(nums[i]);
        else *it = nums[i];
    }
    return res.size();
}
};

python解法如下:

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        n = len(nums)
        def lower_bound(arr, l, r, value):
            while l < r:
                mid = (l + r) // 2
                if arr[mid] < value:
                    l = mid + 1
                else:
                    r = mid
            return l
        
        dp = []
        for n in nums:
            i = lower_bound(dp, 0, len(dp), n)
            if i == len(dp):
                dp.append(n)
            else:
                dp[i] = n
        return len(dp)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值