Leetcode53. 最大子序和

Leetcode53. 最大子序和

题目:
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

题解:
方法一:暴力法
两个for循环
时间复杂度 O(n2),空间复杂度 O(n)
scala代码如下:

def maxSubArray(nums: Array[Int]): Int = {
    var sum = nums(0)
    for (i <- 0 until nums.length) {
      var tmp = 0
      for (j <- i until nums.length) {
        tmp = tmp + nums(j)
        if (tmp > sum) {
          sum = tmp
        }
      }
    }
    sum
  }

方法二:动态规划法
动态规划的是首先对数组进行遍历,当前最大连续子序列和为 sum,结果为 ans
如果 sum > 0,则说明 sum 对结果有增益效果,则 sum 保留并加上当前遍历数字
如果 sum <= 0,则说明 sum 对结果无增益效果,需要舍弃,则 sum 直接更新为当前遍历数字
每次比较 sum 和 ans的大小,将最大值置为ans,遍历结束返回结果
时间复杂度:O(n)
scala代码如下:

def maxSubArray2(nums: Array[Int]): Int = {
    var tmp = nums(0)
    var sum = tmp
    for (j <- 1 until nums.length) {
      // 当当前序列加上此时的元素的值大于tmp的值,说明最大序列和可能出现在后续序列中,记录此时的最大值
      if (tmp > 0) {
        tmp = tmp + nums(j)
        sum = Math.max(sum, tmp)
      } else {
        //  当tmp(当前和)小于下一个元素时,当前最长序列到此为止。以该元素为起点继续找最大子序列,
        //  并记录此时的最大值
        tmp = nums(j)
        sum = Math.max(sum, tmp)
      }
    }
    sum
  }

方法三:分治法
java代码如下:

public int maxSubArray(int[] nums) {
        //分治法
        //每层递归将数组均匀分成两半,三种情况:
        //1.最大子序和在左边
        //2.最大子序和在右边
        //3.最大子序和横跨左右
        return maxSubArray1(nums, 0, nums.length - 1);
    }
    public int maxSubArray1(int[] nums, int l, int r) {
        //分解到只有一个数时,返回该值
        if (l == r)
            return nums[l];
        int mid = (l + r) / 2;
        //递归求左右最大子序和
        int resL = maxSubArray1(nums, l, mid);
        int resR = maxSubArray1(nums, mid + 1, r);
        /**
         从mid向两边求最大子序和maxSumL,maxSumR,第三种情况最大子序和是maxSumL + maxSumR
         */
        int maxSumL = nums[mid];
        int maxSumR = nums[mid + 1];
        int sumL = 0;
        int sumR = 0;
        //计算mid左边的最大子序和
        for (int i = mid; i >= l; i--) {
            sumL += nums[i];
            if (sumL > maxSumL)
                maxSumL = sumL;
        }
        //计算mid右边的最大子序和
        for (int j = mid + 1; j <= r; j++) {
            sumR += nums[j];
            if (sumR > maxSumR)
                maxSumR = sumR;
        }
        int resM = maxSumL + maxSumR;
        //返回resL, resM, resR三者最大值
        return Math.max(resM, (resL > resR ? resL : resR));
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值