Java&LeetCode 初入门——053. 最大子序和

Java&LeetCode 初入门——053. 最大子序和


文内代码全部采用JAVA语言。

题目

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6

个人解法

本人表示本人太渣了,这题完全没想到如何降低复杂度,除了遍历还是遍历。个人代码以及长到超出时间限制,哭晕在厕所。以后还是要多学习才行。就不把我的代码贴出来丢人现眼了。直接学习大神们的解法吧。

大神解法

思路

其实有一个想法很好理解,就是当前面几个数的和小于0时,就没必要带上这几个数了,因为越带越小。比如[-1,-2,5,7,-3,-4,5],从前往后依次看,第一个读取的数是-1,虽然是负数,但没有读取下一个数之前,它是目前的最大值,放在res中。但是负数对于求和取最大值起到的是反作用,所以如果取下一个值的时候,还不如丢掉-1,直接取-2,也比(-1)+(-2)来的划算。第二个和值直接为-2,放在sum中,和res比较,取较大值放在res中。目前的sum依旧小于0,对和值没有帮助,第三个和值直接为5,放在sum中,和res比较,取较大值放在res中。以此类推。

其实简单来讲就是一个指针,从头指到尾。继续看[-1,-2,5,7,-3,-4,5],看指针前面的sum是不是大于0,大于0的sum的子序列对整个连续子数组的最大值有帮助。比如指针指到7时,7前面连续的最大的sum是5,那么整个连续子数组可以纳入5。小于0的sum对整个连续子数组的最大值起反作用,直接抛弃前面的sum。比如指针指到5时,前面的sum=-2,没有帮助,还不如不要,所以指针5时,连续子数组中只有[5]。

自己找个数组调试一遍,很快就能明白了。

算法

16 ms, 在Maximum Subarray的Java提交中击败了60.83% 的用户。
我觉得挺厉害的了,能想到这样的解法真是666(忽略我的垃圾水平)。

class Solution {
    public int maxSubArray(int[] nums) {
        int res = nums[0];
        int sum = 0;
        for (int num : nums) {
            if (sum > 0)
                sum += num;
            else
                sum = num;
            res = Math.max(res, sum);
        }
        return res;
    }
}

范例区最快的解法

class Solution {
    public int maxSubArray(int[] nums) {
        int sum = 0, max = Integer.MIN_VALUE;
        for(int i = 0; i < nums.length; i++){
            sum = sum<0? nums[i] : (sum+nums[i]);
            max = Math.max(sum, max);
        }
        return max;
    }
}

区别不大,只是在于max的初始值和一个三元运算符,思路基本一致。

猜你喜欢

转载自blog.csdn.net/qq_27480345/article/details/86095087