Kadane 算法

2024 年 8 月 28 日 | 阅读 6 分钟

Kadane 算法是一种动态规划方法,用于解决最大子数组问题,即在一个数字数组中找到和最大的连续子数组。该算法由 Jay Kadane 于 1984 年提出,时间复杂度为 O(n)。

Kadane 算法的历史

Kadane 算法以其发明者 Jay Kadane 的名字命名,他曾是卡内基梅隆大学的计算机科学教授。他于 1984 年在《ACM 会刊》上发表的题为“最大子数组和问题”的论文中首次描述了该算法。

寻找最大子数组的问题自 20 世纪 70 年代以来一直被计算机科学家研究。它是算法设计和分析领域中一个众所周知的问题,在信号处理、金融和生物信息学等广泛领域都有应用。

在 Kadane 算法之前,已经提出了其他解决最大子数组问题的算法,例如检查所有可能子数组的暴力方法和分治算法。然而,这些算法的时间复杂度更高,效率不如 Kadane 算法。

Kadane 算法在计算机科学中得到广泛应用,并已成为动态规划的经典范例。其简洁性、高效性和优雅性使其成为最大子数组问题的流行解决方案,也是算法设计和分析中的宝贵工具。

Kadane 算法的工作原理

该算法通过遍历数组并跟踪每个位置结束的子数组的最大和来工作。在每个位置 i,我们有两个选择:要么将位置 i 的元素添加到当前最大子数组,要么在位置 i 处开始一个新的子数组。这两个选项中的较大者是该位置 i 结束的最大子数组。

我们维护两个变量:max_so_far(到目前为止看到的最大和)和 max_ending_here(当前位置结束的最大和)。算法从将这两个变量都设置为数组的第一个元素开始。然后,我们从第二个元素开始遍历数组直到末尾。

在每个位置 i,我们通过取当前元素与当前元素加上前一个最大子数组的和之间的较大值来更新 max_ending_here。然后,我们将 max_so_far 更新为 max_so_far 和 max_ending_here 之间的较大值。

该算法返回 max_so_far,即数组中任何子数组的最大和。

以下是 Kadane 算法的步骤

1. 将两个变量 **max_so_far** 和 **max_ending_here** 初始化为数组的第一个元素。

max_so_far = arr[0]

max_ending_here = arr[0]

2. 从第二个元素开始遍历数组直到末尾

for i from 1 to n-1 do

3. 计算当前位置结束的最大和

max_ending_here = max(arr[i], max_ending_here + arr[i])

4. 将 max_so_far 更新为 max_so_far 和 max_ending_here 之间的较大值

max_so_far = max(max_so_far, max_ending_here)

5. 返回 max_so_far 作为数组中任何子数组的最大和。

Kadane 算法的时间复杂度为 O(n),其中 n 是输入数组的长度。这使其成为解决最大子数组问题的非常高效的解决方案。

示例

让我们通过一个例子来看看 Kadane 算法是如何工作的

假设我们有以下整数数组

我们要找出这个数组的最大子数组和。我们可以应用 Kadane 算法来解决这个问题。

我们从初始化两个变量开始

  • max_so_far:此变量将跟踪我们迄今为止看到的最大子数组和。
  • max_ending_here:此变量将跟踪当前索引结束的最大和。

然后,我们从第二个元素开始遍历数组

通过将当前元素加到前一个和来更新当前和

更新迄今为止看到的最大和

在每次迭代中,我们通过将当前元素加到前一个和或在当前元素处开始一个新的子数组来更新当前和。然后,我们通过将当前和与迄今为止的最大和进行比较来更新迄今为止的最大和。

遍历完整个数组后,max_so_far 的值将是给定数组的最大子数组和。

在此示例中,最大子数组和为 6,对应于子数组 [4, -1, 2, 1]。

Java 代码实现

输出

Enter the size of the array : 9
Enter the elements of the array : 
-2 1 -3 4 -1 2 1 -5 4
The Maximum contiguous sum in the array is : 6

C++ 中的代码实现

输出

Maximum contiguous sum in the array is : 7

Kadane 算法的优点和缺点

Kadane 算法的优点

  • 效率:Kadane 算法的时间复杂度为 O(n),这使其在解决最大子数组问题方面非常高效。这使其成为处理大型数据集的绝佳解决方案。
  • 简单性:与分治算法等解决最大子数组问题的其他算法相比,Kadane 算法相对容易理解和实现。
  • 空间复杂度:Kadane 算法的空间复杂度为 O(1),这意味着它使用的内存量与输入数组的大小无关,是恒定的。
  • 动态规划:Kadane 算法是动态规划的经典范例,动态规划是一种将问题分解为更小的子问题并将这些子问题的解存储起来以避免冗余计算的技术。

Kadane 算法的缺点

  • 只找和,不找子数组本身:Kadane 算法只找到子数组的最大和,而找不到实际的子数组。如果您需要找到具有最大和的子数组,则需要相应地修改该算法。
  • 不能很好地处理负数:如果输入数组只有负数,算法将返回最大的负数而不是 0。可以通过在算法中添加一个额外的步骤来检查数组是否只有负数来克服这一点。
  • 不适用于非连续子数组:Kadane 算法专门用于连续子数组,可能不适用于解决涉及非连续子数组的问题。

Kadane 算法的应用

它有一些应用,例如以下

  • 最大子数组和:如我们在上面的示例中看到的,Kadane 算法用于查找整数数组的最大子数组和。这是计算机科学中的一个常见问题,在数据分析、金融建模和其他领域都有应用。
  • 股票交易:Kadane 算法可用于在给定的一天找到买卖股票可以获得的最大利润。算法的输入是股票价格数组,输出是不同时间买卖股票可以获得的最大利润。
  • 图像处理:Kadane 算法可在图像处理应用中使用,以查找满足特定条件的像素的最大连续区域,例如具有特定颜色或亮度。这对于对象识别和分割等任务很有用。
  • DNA 测序:Kadane 算法可在生物信息学中使用,以查找满足特定条件的 DNA 的最长子序列。例如,可用于查找两个 DNA 序列之间的最长公共子序列,或查找不包含某些模式的最长子序列。
  • 机器学习:Kadane 算法可在某些机器学习应用中使用,例如强化学习和动态规划,以找到最大化奖励函数的最佳策略或行动序列。

因此,我们可以说 Kadane 算法的优点使其成为解决最大子数组问题的绝佳解决方案,尤其适用于大型数据集。但是,在使用它进行特定应用时,必须考虑其局限性。


下一个主题Dijkstra 算法示例