【面试-leetcode53】最大子数组和(贪心算法+动态规划)

lxf2023-07-09 18:20:01

【面试-leetcode53】最大子数组和(贪心算法+动态规划)

这是leetcode面试刷题一题多解系列的第4篇,求最大子数组之和,练习下简单的动态规划和分治算法。

题目

今天跟大家一起看一道经典的动态规划问题,了解下动态规划的核心思想,确定状态转移方程,最大子数组和。

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

来源:力扣(LeetCode)
链接:leetcode.cn/problems/ma…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解1---贪心算法

贪心算法的核心是每次选择当前看起来最优的解,希望最终得到全局最优的解。贪心算法通常能解决一些特殊问题,例如最短路径问题、背包问题、最小生成树等,下面这道题比较简单,主要是让大家感受下贪心的基本思想。

var maxSubArray = function(nums) {
    // 定义初始值为数组的第一个元素
    let ans = nums[0];
    // 定义一个变量sum,用于存储当前连续子数组的和,初始值为0
    let sum = 0;
    for(const num of nums) {
        // 如果当前连续子数组的和大于0,则将当前元素加到连续子数组中
        if(sum > 0) {
            sum += num;
        } 
        // 否则,更新连续子数组和为当前元素
        else {
            sum = num;
        }
        // 更新最大子数组和
        ans = Math.max(ans, sum);
    }
    // 返回最大子数组和
    return ans;
}; 

在这个算法中,每次循环时,我们考虑的是当前连续子数组的和是否大于0。如果是,则将当前元素加入到连续子数组中,以期望得到更大的和;否则,重新将当前元素作为新的连续子数组的第一个元素,继续向后遍历。这种做法可能不是最优解,但通过不断地贪心选择,最终可以得到全局最优解,即整个数组中连续子数组的最大和。 我们只需要遍历一遍数组即可求得答案,所以时间复杂度是 O(N), 只需要常数空间,与输入数组长度无关,所以空间复杂度 O(1)。

题解2---动态规划

动态规划是一种解决多阶段决策过程中的最优化问题的算法思想,其核心思想是将问题分解为若干个子问题,并存储已经求解过的子问题的解,以便在求解当前问题时能够复用这些子问题的解,从而避免重复计算。

动态规划的核心是找出转移方程,转移方程是指根据子问题之间的关系,定义子问题之间的求解方程,这道题的转移方程是:f(i)=max{f(i−1)+nums[i],nums[i]},其中f(i) 代表以第i个数结尾的「连续子数组的最大和」,利用这个状态方程很容易就能编写出下面的代码

var maxSubArray = function(nums) {
    // pre为当前位置之前的子数组的最大和
    // maxAns为找到的最大子数组的和
    let pre = 0, maxAns = nums[0];
    nums.forEach((x) => {
        // 这个算法的核心状态转移方程
        pre = Math.max(pre + x, x);
        // 和之前的最大值比较,求出新的最大值
        maxAns = Math.max(maxAns, pre);
    });
    return maxAns;
};

我们只需要遍历一遍数组即可求得答案,所以时间复杂度是 O(N), 只需要常数空间,所以空间复杂度 O(1)。

本篇求解连续最大子数组和使用了两种算法,其中贪心算法总体来说简单易懂,通常在一些特殊问题的解决上有着较好的效果,但是使用的条件比较苛刻,首先要保证只考虑局部最优解是否能够得到全局最优解,对于数据的要求也比较高;动态规划算是可以得到全局最优解,并且通常可以通过一些技巧进行性能的优化,但是算法的难度较高,状态转移方程通常比较难确定。

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!