算法第一课(复杂度与逐步优化思想)

该笔记整理自七月在线网(https://www.julyedu.com )的算法视频课程

一、介绍

算法很重要,是解决问题的步骤,具有有穷性,确定性、可行性、输入输出。
面试时面试官看重的是解决问题的能力,从暴力解法改良到高效解法。即使不能一下子想到最优算法,也要有自己想法,然后一步步优化去冗余步骤(下面会用一道例题体现这个过程)。

二、复杂度

常用大O表示法。
时间:基本操作次数(汇编指令条数)
空间:占用内存字节数
区别:空间可再利用

常见时间复杂度分析方法 :

  1. 数循环次数
  2. 均摊分析
  3. 递归式——主定理

基本运算如+-*/:O(1)
问题规模可按分数减小,如二分查找:O(logn)
线性查找:O(n)
朴素最近点对,选择排序:O(n²)
Floyd,普通矩阵乘法:O(n³)
O(nlogn),快排期望复杂度,一般为归并排序,堆排序以及相关的,也是基于比较排序的算法下界。

总结:
优秀:O(1)<O(logn)<O(n)<O(nlogn) 面试时当复杂度是这些时一般就不用再优化了
可能需要继续优化:O(n²)<O(n³)<O(n!)

三、分治法主定理(只是一个公式,面试一般不考,了解即可)

递归式与分治方法是紧密相关的,因为使用递归式可以清晰的刻画分治算法的运行时间。
主方法如下:
T(n) = aT(n/b) + f(n)

a>=1 b>1 f(n) 是给定的函数。这种形式的递归式很常见。刻画了一个分治算法。生成a个子问题。每个子问题是原来的1/b。分解和合并步骤共消耗f(n)
主方法是计算时间复杂度的时候用的。


利用上面的这个定理就可以计算递归式的时间复杂度了,这里面的1)与3)换句话说就是1)f(n)nlogb^a
T(n) = 9T(n/3) + n 那么计算其渐进界就是nlog39=n2

四、均摊法

多个操作一起算复杂度,再除操作次数得每次操作复杂度。基本理念是,给定一连串操作,大部分的操作是非常廉价的,有极少的操作可能非常昂贵,因此一个标准的最坏分析可能过于消极了。因此,其基本理念在于,当昂贵的操作特别少的时候,他们的成本可能会均摊到所有的操作上。

五、例题

leetcode 53. Maximum Subarray 注意思考优化问题复杂度,去除冗余步骤的过程

题目: 给定数组a[1…n],求最大子数组和,即找出1<=i<=j<=n, 使a[i]+a[i+1]+…+a[j]最大

PS:建议直接在leetcode上写代码,培养好代码习惯,训练徒手写代码能力。

1.暴力枚举O(n³)

首先可以想到用二重循环

    public class Solution {
        public int maxSubArray(int[] nums) {
            int max=nums[0];
            int n = nums.length;
            for(int i=0;i<n;i++){
                for(int j=i;j<n;j++){
                    int result = 0;
                    for(int k=i;k<=j;k++){                 
                        result=result+nums[k];
                    }
                    if(result>max)
                        max=result;
                }
            }
            
                return max;
        }
    }

提交后发现超时,(面试时拿到问题如果没有好的想法可以先讲一下暴力解法,比较差的算法面试官也可以接受,一定要有思路。面试官一定会继续问能不能优化,接下来继续思考有没有冗余的步骤可以去掉

2.优化枚举,二重循环

思考上述过程是否有冗余步骤:计算过子数组A的和后,想计算子数组AB的和,可以像上面一样找到AB,循环累加AB,但是计算A的和的过程重复了。可以直接在A的和基础上继续累加B。
时间复杂度 O(n2) 附加空间复杂度 O(1)

    public class Solution {
        public int maxSubArray(int[] nums) {
            int max=nums[0];
            int n = nums.length;
            for(int i=0;i<n;i++){
                int result = 0;
                for(int j=i;j<n;j++){
                    result=result+nums[j];
                    if(result>max)
                        max=result;
                }
            }
            return max;
        }
    }

虽然复杂度降低,但提交后依然超时。

3.贪心法,一重循环,O(n)

此时面试官应该会继续提醒你优化。继续思考,刚刚我们找了所有的子数组及其累加和,方法2也只是优化了累加部分,令循环累加O(n)变成O(1)。但各子数组是有重叠的,如下图,



当发现子数组A的和小于零时,其实我们就不用计算子数组AB的和了,直接计算B即可,因为A的和小于零,AB一定小于B,也就是所有以A为前缀的子数组都不用计算了。换言之,只有当A的和>0时,A才会对子数组累加结果增长有帮助。

贪心法可以理解为只要对自己好的,对自己不利的一律不要。若A<0,它对后面子数组求和结果的贡献一定是负的,所以不要,若A>0,A的贡献是正的(可以令子数组和变更大),要它。不要小于零的,只要大于零的。由此想到下面算法。

时间复杂度 O(n) 附加空间复杂度 O(1)。
累加子数组,当发现sum小于零时,令sum=0(丢弃前面的累加和,继续计算后面的和,也就是当发现前面的A的sum为零时,跳过A为前缀的子数组,直接计算A后面的和),丢弃之前已经把前面的最大子数组和保存在ans里,不用担心最大子数组和出现在前面怎么办(每次计算sum后都比较更新ans)。

    public class Solution {
        public int maxSubArray(int[] nums) {
            int max=nums[0];
            int n = nums.length;
            int sum = 0;
            for(int i=0;i<n;i++){
                sum+=nums[i];
                if(sum>max)
                    max=sum;
                if(sum<0){
                    sum=0;
                    }
                
            }
            return max;
        }
    }

AC!
时间复杂度O(n),此时如果面试官还问可不可以优化时,我们就可以自信的说,这应该已经是最优解了😁
这道题很经典,理解拿到一个问题给出一个解然后逐步优化的思想。

PS:在算法优化中还有一种用空间换时间的想法,类似桶排序那种思路,现在暂时想不到例题,这篇笔记就不写了,以后遇到类似问题再总结。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 算法复杂度 时间复杂度 空间复杂度 什么是时间复杂度 算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗...
    KODIE阅读 3,233评论 0 9
  • 算法的时间复杂度和空间复杂度-总结通常,对于一个给定的算法,我们要做 两项分析。第一是从数学上证明算法的正确性,这...
    Explorer_Mi阅读 1,444评论 0 1
  • 1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不...
    曲终人散Li阅读 3,293评论 0 19
  • 喜欢风 却没有风 那就跑起来
    辛安小阅读 627评论 19 50
  • 致良知是一种伟大的力量! 2017年6月13日星期二 涌泉学苑二期学习班 第13天 北大组+23+孙晓君打卡记录:...
    闻君儿阅读 430评论 0 0