刷题测试:求数组最大子序和

252 阅读2分钟

一、题目描述:

53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。

二、思路分析:

所有的算法题,都是可以通过暴力方式解决的。 先上循环思路:

  1. 将所有长度的数组通过双层循环,都截取出来保存在一个新数组中
  2. 通过循环数组中所有的截取项,加和对比找出其中的最大值并返回
var maxSubArray = function(nums) {
  let max = '', allUnion = [];
  const length = nums.length;
  for (let i = 1; i <= length; i += 1) {
    for (let j = 0; j < length; j += 1) {
      if (j + i > length) break;
      allUnion.push(nums.slice(j, j+i))
    }
  }
  allUnion.forEach((x) => {
    let sum = x.reduce((prev, next) => prev + next, 0)
    if (sum > max || max === '') {
      max = sum
    }
  })
  return max;
}

上面代码看似没啥毛病,提交测试会报:内存溢出,多次循环面对大量数据免不了内存会爆了。

想不到其他的方法,那就看看题解吧。

官方解法

贪心算法

若当前指针所指元素之前的和小于0,则丢弃当前元素之前的序列 时间复杂度:O(n) 空间复杂度:O(1)

var maxSubArray = function(nums) {
    let pre = 0, maxAns = nums[0];
    nums.forEach((x) => {
        pre = Math.max(pre + x, x);
        maxAns = Math.max(maxAns, pre);
    });
    return maxAns;
};

动态规划

若前一个元素大于0,则将其加到当前元素上,最后取列表中最大元素得到最大子序和 时间复杂度:O(n) 空间复杂度:O(1)

var maxSubArray = function(nums) {
    let pre = 0;
    nums = nums.map((x) => {
        if (pre > 0) {
            x += pre
        }
        pre = x;
        return x;
    })
    return Math.max(...nums);
}

四、总结:

看了题解,依然不能解惑

但至少弄我得先弄明白:空间复杂度、时间复杂度、动态规划、贪心算法,这四个概念都是啥意思

  • 空间复杂度:一个算法在运行过程中临时占用存储空间大小的量度
  • 时间复杂度:定性描述该算法的运行时间
  • 动态规划:将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解
  • 贪心算法:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。

题,第一遍看上去如果想不到其他解法就去看题解,不要浪费时间,有一个大概的印象就好不求一遍就会