前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法初步 基本概念 最大子数组和

算法初步 基本概念 最大子数组和

作者头像
我是李超人
发布2020-08-20 20:04:37
3850
发布2020-08-20 20:04:37
举报

算法是研究时空复杂度的,时空复杂度使用大O表示。

时间:基本操作次数(汇编指令条数,比如算法执行完需要n行指令,则时间复杂度为O(n),时间复杂度是忽略前面的系数的,算法执行需要2n行指令,时间复杂度也是O(n),所以不用考虑一行指令对应多条汇编,系数是忽略的。O(n^2 + n)可以认为是o(n^2),因为n的平方远大于n) 空间:占用内存字节数

优秀的算法:O(1) < O(logn) < O(n^1/2) < O(n) < O(nlogn) 需要优化的算法:O(n^2) < O(n^3) < O(2^n) < O(n!)

案例 最大子数组求和 leetcode 53题 给定数组a[1…n],求最大子数组和,即找出1<=i<=j<=n,使a[i]+a[i+1]+…+a[j]最大。

方法一:暴力枚举,时间复杂度为o(n^3),无法通过leetcode,显示超时。 时间复杂度为o(n^3),空间复杂度o(1)

代码语言:javascript
复制
class Solution {
    public int maxSubArray(int[] nums) {
        int sum = 0;
        int msum = Integer.MIN_VALUE;
        for(int i=0;i<nums.length;i++){
            for(int j=i;j<nums.length;j++){
                for(int k=i;k<=j;k++){
                    sum+=nums[k];
                }
                if(msum<sum){
                    msum = sum;
                }
                sum = 0;
            }

        }
        return msum;
    }
}

方法二:优化枚举,时间复杂度为o(n^2),空间复杂度为o(n)(很多部分都重复加了,要去除冗余,直接通过了leetcode,很神奇,执行时间为66ms,超过了百分之4的人。

代码语言:javascript
复制
class Solution {
    public int maxSubArray(int[] nums) {
        int sum = 0;
        int msum = Integer.MIN_VALUE;
        int[] s = new int[nums.length + 1];
        s[0] = 0;
        for(int i=0;i<nums.length;i++){
            s[i + 1] = s[i] + nums[i];
        }
        for(int i=0;i<nums.length;i++){
            for(int j=i;j<nums.length;j++){
                sum = s[j+1] - s[i];
                if(msum<sum) msum = sum;
            }
        }
        return msum;
    }
}

方法三:假设s[i] 为nums[0] 到nums[i]的和,那么要想求出最大子数组和,就需要得到max(s[j] - s[i]),将s[j]固定,则需要求min(s[i]),所以此问题由最大子数组和转换成了求最小和(最小s[i])的问题,这次提交执行时间为10ms,超过了47.22%的人 (经验:求和变求差 求积变求和 求指数变对数 求最大变求最小),时间复杂度为O(n),空间复杂度为O(n)。

代码语言:javascript
复制
class Solution {
    public int maxSubArray(int[] nums) {
        int msum = Integer.MIN_VALUE;
        int si = 0;
        int sj = 0;
        int minsi = 0;
        for(int j = 0; j<nums.length;j++){  
            sj += nums[j];
            if(si < minsi){    //min[0,6] = min(min[0,5] [6])  求最小和可以通过增量来实现,si的(0,6)的最小和其实就是(0,5)的si最小和和si[6]最比较,这种增量方式的转换技巧很实用
                minsi = si;
            }
            if(sj - minsi > msum){
                msum = sj - minsi;
            }
            si += nums[j];
        }
        return msum;
    }
}

方法四:将以上代码稍微调整一下就是贪心算法了 时间8ms,超过89.81%。贪心算法的思路比较难以理解,后面介绍贪心算法的时候再回过头来看看。

代码语言:javascript
复制
class Solution {
    public int maxSubArray(int[] nums) {
        int msum = Integer.MIN_VALUE;
        int sum = 0;
        for(int j = 0; j<nums.length;j++){
            sum += nums[j];
            if(sum>msum) msum = sum;
            if(sum < 0) sum = 0;
        }
        return msum;
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-11-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档