300. Longest Increasing Subsequence

class Solution {
    public int lengthOfLIS(int[] nums) {
        int []tails=new int[nums.length];
        int size=0;
        for(int x:nums)
        {
            int i=0,j=size;
            while(i!=j)
            {
                int m=i+(j-i)/2;
                if(tails[m]<x)
                    i=m+1;
                else
                    j=m;
            }
            tails[i]=x;
            if(i==size)++size;
        }
        return size;
    }
}

这题是典型的考察dp并且是非常直白的..不像有些题目很绕,想半天才知道是dp

dp的做法就是分配一个数组,  dp[i] 代表 第i 个位置的最长递增数组长度

递推公式   if (num[i]>num[k]) dp[i]=max(dp[k]+1,dp[i])    0<=k<i     时间复杂度 O(n2)   n是数组长度;      其实精确计算复杂度应该是O(1+2+3+...+n)  = O(n*(n-1)/2) = O( (n2-n)/2)

好了, 上面给出的更加高效的办法, 用二分查找做到了 O(nlogn);

原理如下

1 数组长度为n,  所以我们可以找出 长度 为  1,2,3,4, ....  k  的递增数组

2  设定 数组=   1,2,3,0

长度=1  递增数组   [1], [2] , [3] , [0]

长度=2 递增数组   [1,2]  [2,3] [1,3] 

长度=3                   [1,2,3]

取每个数组的末尾值, 并且值最小    分别是  0 , 2, 3  ;   这几个数的长度是3, 所以答案就是3

3 实现过程

分配一个数组来存放不同长度的递增数组的末尾值的最小取值.. 非常绕

int  tail = new  int[]

遍历数组;如果 num[i] 比 tail 末尾值还大, 插入末尾

如果nums[i] 值在tail 的之内;  找到一个位置替换,   具体是   tail[i] < num[j] <= tail[i+1]

因为用到了二分查找, 所以复杂度变成了logn

原文地址:https://www.cnblogs.com/lychnis/p/9309758.html