题解 | #子数组的最大累加和问题#

子数组的最大累加和问题

http://www.nowcoder.com/practice/554aa508dd5d4fefbf0f86e5fe953abd

题解一: 动态规划
题解思路:使用dp数组表示子问题累加和, ans表示当前数组累加和最大值
图示:
图片说明

复杂度分析:
时间复杂度:O(N)
空间复杂度:O(N)
实现如下:

class Solution {
public:
    /**
     * max sum of the subarray
     * @param arr int整型vector the array
     * @return int整型
     */
    int maxsumofSubarray(vector<int>& arr) {
        // write code here
        int len = arr.size()-1;
        int dp[len+1]; 
        memset(dp, 0, sizeof(dp));
        dp[0] = arr[0];
        int ans = arr[0];
        for(int i = 1;i<=len; i++){
            dp[i] = dp[i-1]+arr[i] > arr[i] ? dp[i-1]+arr[i] : arr[i];
            ans = max(dp[i],ans);  //更新最大累加和
        }
        return ans;

    };
};

题解二:优化动态规划空间复杂度
题解思路: 可以使用一个cur_sum表示当前累加和,如果在arr[i]处,cur_sum < 0, cur_sum = arr[i]; ans依然保存当前最大累加和。
复杂度分析:
时间复杂度:O(N)
空间复杂度:O(1)
实现如下:

class Solution {
public:
    int maxsumofSubarray(vector<int>& arr) {
        int ans = arr[0];
        int cur_max = arr[0];
        for(int i = 1;i<arr.size();i++){
            cur_max = cur_max + arr[i] > arr[i] ? cur_max+arr[i] : arr[i]; // 更新当前累积和
            ans = max(cur_max , ans);  // 更新最大累积和
        }
        return ans;
    }
};

题解三:二分法
题解思路:将数组分为两部分,最大和分为三种情况。
图示:
图片说明

复杂度分析:
时间复杂度:O(NlogN)
空间复杂度:O(logN) : 递归栈深度

实现如下:

class Solution {
public:
      int merge_max(int left,int mid,int right,vector<int>& arr){
        int left_sum = 0;
        int leftmax = INT_MIN;
        // 从mid开始,向左计算累加和
        for(int i = mid;i>=left;i--){
            left_sum += arr[i];
            leftmax = max(left_sum,leftmax);
        }
        int right_sum = 0;
        int rightmax = INT_MIN;
        // 从mid开始,向左计算累加和
        for(int i = mid+1;i<=right;i++){
            right_sum += arr[i];
            rightmax = max(right_sum, rightmax);
        }
        return rightmax+leftmax;  // 左右最大累加和相加
    }
    int search_max(int left,int right,vector<int>& arr){
        if(left==right) return arr[left];
            int mid = (left+right)>>1;
            int left_sum = search_max(left, mid, arr);  //求左边最大值
            int right_sum = search_max(mid+1,right,arr);  //求右边累加最大值
            int merge_sum = merge_max(left,mid,right,arr);  //合并累加最大值
            return max(max(left_sum,right_sum),merge_sum);
    }
    int maxsumofSubarray(vector<int>& arr) {
        return search_max(0, arr.size()-1, arr);
    }
};
牛客网编程题题解 文章被收录于专栏

本专栏记录在牛客网上AC的每一题,写下题解。 未来2年完成2000编程题的题解。 2021.12.29更新,最进准备毕设,断更了,会尽快做完毕设,继续做这一件事情

全部评论

相关推荐

无一技之长怎么办:别去右边,售前,实施,需求分析一起,这是把人当牛马用啊,快跑,这些岗位天花板很低的
点赞 评论 收藏
分享
会飞的猿:我看你想进大厂,我给你总结一下学习路线吧,java语言方面常规八股要熟,那些java的集合,重点背hashmap八股吧,jvm类加载机制,运行时分区,垃圾回收算法,垃圾回收器CMS、G1这些,各种乐观锁悲观锁,线程安全,threadlocal这些。在进阶一些的比如jvm参数,内存溢出泄漏排查,jvm调优。我这里说的只是冰山一角,详细八股可以去网上找,这不用去买,都免费资源。mysql、redis可以去看小林coding,我看你简历上写了,你一定要熟,什么底层b+树、索引结构、innodb、mvcc、undo log、redo log、行级锁表级锁,这些东西高频出现,如果面试官问我这些我都能笑出来。消息队列rabbitmq也好kafka也好,学一种就行,什么分区啊副本啊确认机制啊怎么保证不重复消费、怎么保证消息不丢失这些基本的一定要会,进阶一点的比如LEO、高水位线、kafka和rocketmq底层零拷贝的区别等等。计算机网络和操作系统既然你是科班应该理解起来问题不大,去看小林coding这两块吧,深度够了。spring boot的八股好好看看吧,一般字节腾讯不这么问,其他的java大厂挺爱问的,什么循环依赖啥的去网上看看。数据结构的话科班应该问题不大,多去力扣集中突击刷题吧。项目的话其实说白了还是结合八股来,想一想你写的这些技术会给你挖什么坑。除此之外,还有场景题、rpc、设计模式、linux命令、ddd等。不会的就别往简历上写了,虽然技术栈很多的话好看些,但背起来确实累。总结一下,多去实习吧,多跳槽,直到跳到一个不错的中厂做跳板,这是一条可行的进大厂的路线。另外,只想找个小厂的工作的话,没必要全都照这些准备,太累了,重点放在框架的使用和一些基础八股吧。大致路线就这样,没啥太多难度,就是量大,你能达到什么高度取决于你对自己多狠,祝好。
点赞 评论 收藏
分享
评论
2
1
分享

创作者周榜

更多
牛客网
牛客企业服务