每日一练之最长上升子序列

最长上升子序列

OJ 地址:最长上升子序列
在这里插入图片描述

详细解法见这篇博客:最长上升子序列

class Solution {
public://
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size();
        if(n <= 1) return n;
        //tail[i]表示长度为i的递增序列末尾的数字
        //tail[]数组性质:tail[0]<tail[1]<...tail[n] !!!
        vector<int> tail(n);//初始化为n个值为0的元素
        //1.len为当前最长的递增序列长度(为方便操作将len减1,从0开始,最后再加上1)
        int len=0;
        tail[0]=nums[0];
        //2.每次读入一个新元素nums[i]
        for(int i=1;i<n;i++)
        {//遍历nums[]中的数
            if(nums[i] < tail[0])
            {//(1)nums[i]比所有递增序列的末尾都小,则长度为1的序列更新为这个更小的末尾。
                tail[0]=nums[i];
            }
            else if(nums[i] > tail[len])
            {//(2)nums[i]比所有序列的末尾都大,则直接将nums[i]加到后面
                tail[++len]=nums[i];
            }
            else
            {//(3)在中间,则更新那个末尾数字刚好大于等于nums[i]的那个序列,nums[i]替换其末尾数字
                tail[biSearch(tail, 0, len, nums[i])]=nums[i];
            }
        }
        return len+1;
    }
    int biSearch(vector<int>& tail, int low, int high, int target)
    {//由于tail数组是有序的,故可二分查找其中元素
        while(low <= high)//不能是low<high
        {//当low=high时还要进行一次循环!!!
         //此时mid=low=high.若tail[mid]<target,则low=mid+1.而不是直接返回low!!!
            int mid = low + (high-low)/2;
            if(tail[mid] == target) return mid;
            else if(tail[mid] > target)
            {
                high=mid-1;
            }
            else
            {
                low=mid+1;
            }
        }
        return low;
    }
};
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页