最大子数组问题 - 最小值解决方案?

2024-01-11

您是否曾经感觉自己的大脑不适合算法?

我尝试解决最大子数组问题 https://en.wikipedia.org/wiki/Maximum_subarray_problem我在 Codewars 上发现了这个解决方案:

var maxSequence = function(arr){
  var min = 0, ans = 0, i, sum = 0;
  for (i = 0; i < arr.length; ++i) {
    sum += arr[i];
    min = Math.min(sum, min);
    ans = Math.max(ans, sum - min);
  }
  return ans;
}

console.log(maxSequence([-2, 1, -3, 4, -1, 2, 1, -5, -4]));

我了解如何使用线性时间复杂度解决这个问题Kadane's algorithm:

var maxSequence = function(arr){
  let max = 0;
  let localMax = 0;

  for (let i = 0; i < arr.length; i++) {
    localMax = Math.max(localMax + arr[i], arr[i]);
    max = Math.max(localMax, max);
  }

  return max;
}

console.log(maxSequence([-2, 1, -3, 4, -1, 2, 1, -5, -4]));

但我无法理解为什么第一个解决方案有效。我根本无法理解其背后的想法。我觉得需要一点帮助来克服困难。

编辑:这是一个Codepen https://codepen.io/florianmartens/pen/zYoWwVX?editors=1010一些例子


您提供的算法正在做同样的事情,但方式更复杂。为了正确解释它,我将比较代码战争算法您提供的卡丹算法在其执行的各个步骤中。


让我们考虑一下数组:

[2 -4 3 2 6 -10 -12 20]

这里是代码战争算法您提供:

var maxSequence = function(arr){
    var min = 0, ans = 0, i, sum = 0;
    for (i = 0; i < arr.length; ++i) {
        sum += arr[i];
        min = Math.min(sum, min);
        ans = Math.max(ans, sum - min);
    }
    return ans;
}

这是执行卡丹算法维基百科中提到:

def max_subarray(numbers):
"""Find the largest sum of any contiguous subarray."""
best_sum = 0  # or: float('-inf')
current_sum = 0
for x in numbers:
    current_sum = max(0, current_sum + x)
    best_sum = max(best_sum, current_sum)
return best_sum

第一步:-

sum 更改为 2 and min 保持不变. The ans 更改为 2.

第二步:-

sum 更改为 -2 and min 更改为-2。这ans is still2. 这里需要注意一个有趣的事情,根据维基百科对 Kadanes 算法的实现,在第二阶段的值current_sum will change到 0 这是正确的处理方法。

然而在 codewars 的实现中,sum is still-2。如果您更仔细地观察,您会发现sum-min在 codewars 实现中为 0。这是需要注意的非常重要的一点。而不是当 sum 的值达到小于 0 时将其更改为 0。我们存储必须从 sum 中减去以使净和为 0 的最小数。该值存储在min这也解释了为什么它如此命名。

以下是迄今为止变量值的记录:

 sum    min    ans
  2      0      2     //ans = max(0, 2-0)
 -2     -2      2     //ans = max(2, -2+2)    

第三步:-

The sum 更改为 1. min 仍然保持不变。的答案更改为3 哪个是正确的。这是怎么发生的呢?

在 Kadanes 算法中,您可以更改current_sum现阶段为3。在codewars实现中,而不是改变sum到3,他们所做的就是使用a我再次重复的 min 变量存储应该从答案中减去的数字,以便我们获得与 current_sum 中相同的值。从这部分算法来看就更清楚了。

ans = Math.max(ans, sum - min);   //sum-min is current_max

这里当我们减去min从你的sum. 它抵消了你答案中额外的否定。在这个数组 A 中,额外的负数是2 + (-4) = -2。在以下每个步骤中,我们将在这里观察到sum is not包含最大连续子数组和。最大连续子数组总和存储在 sum - min 中。这是这个算法的关键。sum-min 是这里的 current_sum。以下是以下步骤:

sum    min    ans
 1     -2      3      //ans = max(2, 1+2)
 3     -2      5      //ans = max(3, 3+2)
 9     -2      11     //ans = max(5, 9+2)
-1     -2      11     //ans = max(11, -1+2)

有趣的是,观察到即使最后一步中 sum 的值为负数,min 的值也不会改变。这是为什么?答案是不需要。如果你看sum-min在这种情况下,它是 1 且不小于 0。因此如果 A 中的当前索引后面有足够的正数,则 sum-min 的值可能会超过 ans 的当前值。如果你试运行 Kadanes 算法直到这一步,你会注意到即使有current_sum这个阶段不会变成0,而是1。

剩余步骤:-

sum    min    ans
-1     -2      11     //ans = max(11, -1+2)
-13    -13     11     //ans = max(11, -13+13)
 7     -13     20     //ans = max(11,  7+13)

这个实现中最重要的一点是,sum-min这里类似于current_sumKadane 算法。


我还应该提到,您提供的 Kadanes 算法和 codewars 算法将not工作,如果输入数组由所有负数组成。两者都不是为此目的。如果您希望 Kadanes 算法适用于由所有负数组成的数组(将 current_sum 初始化为A[0]).

如果您在理解我的解释时遇到任何问题,请发表评论。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

最大子数组问题 - 最小值解决方案? 的相关文章

  • 如何在 React JS 中根据键创建动态表?

    我正在尝试在 React JS 中创建一个动态表组件 该组件当前只有一个静态标头 其中包括最常见的结果键 有些结果还包含更多信息 例如电话号码 学位 如何根据键 值的存在动态地使用附加列扩展表 我应该与state并在存在时使其可见 或者我应
  • 无法将消息发布到服务工作人员,因为控制器值为空

    我正在尝试做一个website https secure depths 31934 herokuapp com 在 Service Worker 的帮助下可以离线使用 以缓存页面所需的文件 我试图让用户控制他希望缓存的图像 为此 我使用一个
  • 为什么 Jshint 在此 if 语句中说“变量已定义”?

    我有这个代码 if something is true var someVar true else var someVar false JsHint 表示在 else 语句部分 someVar 已被定义 这是为什么 我该如何解决 Thank
  • 如何使用标准 JavaScript 在 CSS 转换结束后立即重新启动它?

    我构建了一种密码生成器 只要倒计时到期 它就会显示新密码 不幸的是 我只设法弄清楚如何运行我的代码一次 倒计时由一个简单的 CSS 过渡组成 我想保留它 因为它比我的其他尝试平滑得多 其中我尝试使用 JavaScript 重复更新宽度 va
  • 在 Cordova 中合并文件的多个部分

    在我的 Cordova 应用程序中 我正在下载任意文件 例如图像或视频文件 这是通过 Cordova 文件传输插件和 Range 标头完成的 因为我需要分段下载文件 我的问题是 我想将几 个小 字节 文件合并回原来的文件中 他们曾经在其中使
  • JavaScript 可以检测用户的浏览器是否支持 gzip 吗?

    我可以使用 JavaScript 来检测用户的浏览器是否支持 gzip 压缩内容 客户端 而不是 Node js 或类似内容 我正在尝试支持以下边缘情况 有很多可能的文件可以加载到特定的 Web 应用程序上 最好在应用程序运行时根据需要加载
  • html 图像 src 调用 javaScript 变量

    这是我的代码 我想问 我怎样才能做到这一点 img src img apple 我一直在尝试使用 call 函数和 document onload 但它根本不起作用 有人可以救我吗 我假设你只是想用 javascript 更新图像 src
  • Twitter Bootstrap - 下拉菜单 - 箭头键不适用于 Firefox 中的输入标签

    要求 我想在带有用户名和密码字段的下拉菜单中放置一个登录表单 我可以做到这一点 除了以下问题之外 一切正常 Issue 打字时我无法使用箭头键 上 下 firefox 当输入位于下拉代码之外时 这很有效 这适用于其他浏览器 例如 googl
  • 个人 Tumblr 帖子上的 Javascript

    我知道您可以编辑在 tumblr 博客上呈现所有帖子博客主页的 html AngularJS 但是 有什么办法可以添加自定义到各个帖子 我想在逐个帖子的基础上做一些 javascript 的东西 但似乎无法找到可以编辑代码的位置 或者 如果
  • 如何用 JavaScript 修复图像透视变形和旋转?

    我有一些用手机拍摄的图像 有没有可以拉直纸张照片并将其压平的 JavaScript 库 例如 我想创建一个矩形图像 该图像没有任何失真 换句话说我想知道如何用 JavaScript 修复透视变形和旋转 例如 我发现下面的示例图像来自this
  • 只保留 A-Z 0-9 并使用 javascript 从字符串中删除其他字符

    我正在尝试验证字符串以使它们成为有效的网址 我只需要保留 A Z 0 9 并使用以下命令从字符串中删除其他字符javascript or jquery 例如 贝儿餐厅 我需要将其转换为 百丽餐厅 所以字符被删除 只保留 A Z a z 0
  • Angular 2 将字符串转换为 md5 哈希

    我找到了ts md5 https www npmjs com package ts md5包 但在示例中它有一个hashStr方法 但现在不行了 类型上不存在属性 hashStr Md5 使用该错误后 该错误会记录在我的控制台中 我怎样才能
  • 使用 nockjs 和 jest 进行 Promise/异步单元测试的代码覆盖率问题

    我使用 NockJS 和 Jest 为 React 应用程序编写了一个简单的 API 调用单元测试 如下所示 AjaxService js export const AjaxService post url data headers gt
  • 寻找簇的中心

    我有以下问题 进行抽象以找出关键问题 我有 10 个点 每个点与其他点有一定距离 我想要 能够找到簇的中心 即与其他点的成对距离最小的点 令 p j p k 表示点 j 和 k 之间的成对距离p i 是簇的中心点 iff p i s t m
  • 根据文本内容从 jquery 对象中过滤元素

    我正在尝试使用contains带有 this 关键字 但它给出了错误 JS function var check ul find li filter function return this contains two css color r
  • 如何使用 jQuery 过滤 DropDownList 中的选项

    我有 2 个 DropDownList 第一个 DropDownList 有 4 个选项 第二个 DropDownList 有 20 个选项 我想要一个选项value 1在第一个 DropDownList 中选择我在第二个 DropDown
  • VS Code 扩展 - 获取完整路径

    我正在为 VS Code 编写一个插件 我需要知道调用扩展的文件的路径 无论是从编辑器上下文菜单或资源管理器上下文菜单调用还是用户只需键入扩展命令 function activate context get full path of the
  • 在 Firestore 文本字段中存储文本文件并删除换行符

    我正在尝试将 CSV 文件存储在 Cloud Firestore 内的文本字段中 然而 Firestore 正在删除所有换行符并将整个 CSV 文件存储为一行 这Firestore 数据类型文档 https firebase google
  • 如何从 Cloud Functions for Firebase 文件夹读取证书文件

    我正在尝试读取 certs 文件夹下的文件 如下所示 functions certs idp public cert perm 这是我用来读取文件的代码 fs readFileSync path join dirname certs idp
  • Safari 扩展将消息发送到特定选项卡

    有没有办法从全局页面发送消息到特定选项卡 我目前正在做的是 在创建选项卡时 注入的脚本会创建一个唯一的 ID 并将包含该编号的消息发送到全局页面 并且全局页面会保存该编号 如果全局页面需要发送一些数据到一个tab 即 tab 3 然后全局页

随机推荐