【手绘漫画】图解LeetCode之最长上升子序列(LeetCode300题),贪心算法 + 二分查找

在这里插入图片描述

图解LeetCode刷题计划

1、写在前面

手绘漫画系列正式上线!!!“图解LeetCode刷题计划” 来了!!!

今天是第五期,争取每天一期,最多两天一期,欢迎大家监督我。。。公众号监督最好!!!
在这里插入图片描述
今日是贪心算法,还有好吃的~
在这里插入图片描述

2、题目

首先看一下题目,
在这里插入图片描述
应该第一时间先想到贪心算法,为什么呢?

如果要使上升子序列尽可能的长,那么就要让序列上升得尽可能慢(最好一次只变化1)。

因为我算法还没学完。。。动态规划还没学。。。这一期就来长长见识吧!

大写的惨字!

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。

在这里插入图片描述
在这里插入图片描述

3、正文

首先分析一下情况,

这里最重要的是一个思想,即贪心算法——考虑如果要使上升子序列尽可能的长,则要让序列上升尽可能的慢,所以需要一个数组来记录,也就是 d

遍历整个数组,寻找上升子序列,只要下一个元素大于上一个元素,就先读入,然后与 d 中保存的最长上升子序列的末尾元素的最小值比较,如果能满足贪心算法,就录入,以此类推。
在这里插入图片描述
这里让人拍手叫绝的一个点就是——3,不知道你看出来为啥了嘛?

复杂度:

  • 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)。数组 nums \textit{nums} nums 长度 n,二分搜索是 O ( log ⁡ n ) O(\log n) O(logn)
  • 空间复杂度: O ( n ) O(n) O(n),长度为 n 的数组 d

在这里插入图片描述

4、代码

int lengthOfLIS(int* nums, int numsSize){
    int len = 1;
    if (numsSize == 0) return 0;
    int d[numsSize+1];
    d[len] = nums[0];
    for (int i = 1; i < numsSize; ++i) {
        if (nums[i] > d[len]){
        	d[++len] = nums[i];
        }
        else{
            int l = 1, r = len, pos = 0; 
            while (l <= r) {
                int mid = l + (r - l)/2;
                if (d[mid] < nums[i]) {
                    pos = mid;
                    l = mid + 1;
                }
                else {
                	r = mid - 1;
                }
            }
            d[pos + 1] = nums[i];
        }
    }
    return len;
}

在这里插入图片描述

5、讨论

1、严格意义上,这个题和二分查找没啥特别大的关系,23333。

一起来看一个实例分析吧:
在这里插入图片描述
在这里插入图片描述

2、为什么数组 d 要是 d[numsSize+1]?

原因很简单,为了保证下标同步。

3、数组 d 是单调递增的嘛?

看了LeetCode上的题解,感觉反证不如直接得来的快,d 其实就是我们需要的最长子序列,因为是上升的,自然得是递增的。
在这里插入图片描述

如果有幸帮到你,请帮我点个【赞】,给个【关注】!如果能顺带【评论】给个鼓励,我将不胜感激。

如果想要更多的资源,欢迎关注 @我是管小亮,文字强迫症MAX~

回复【数据结构】即可获取我为你准备的大礼。

想看更多文(段)章(子),欢迎关注微信公众号「程序员管小亮」~

在这里插入图片描述

©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页