Kadane 的算法是贪心算法还是优化 DP?
Is Kadane's Algorithm Greedy or Optimised DP?
我感觉Kadane的算法是最大子数组真动态规划解法的修改版problem.Why我感觉是这样吗?
我感觉是因为计算最大子数组的方式可以采取:
for(i=0;i<N;i++)
{
DP[i][A[i]]=true;
for(j= -ve maximum ;j<= +ve maximum ;j++)
if(DP[i-1][j])
DP[i][j+A[i]]=true;
}
如果可以用一个以 i-1 结尾的子数组形成 j 个元素 i 可以形成 j+A[i] 使用第 i 个元素并通过在第 i 个位置开始一个子数组单独形成 A[i]
最后我们可以在这个 DP 数组中搜索标记为 true 的最大值 j!
注意:DP[i][j]
表示是否可以使用以i结尾的子数组来生成j!这里我假设 j 也可以是负数。!现在可以很容易地得出 sum+ 一个负数 < sum 。这意味着添加任何负索引无助于获得更好的总和,这就是我们可以删除它们的原因!此外,我们关心最大 j 直到第 i-1
个位置,并将它与 i th
元素连接起来,这让我觉得这是一种贪婪的选择(只是因为最大值 + 元素给了我最大值)。
注意:我现在还没有研究过贪心算法,但我知道什么是贪心选择!
编辑:有人说我的算法没有任何意义所以我试图 post 我的代码让我自己清楚。我没有把 j 当作 -ve,因为它们没有成果。
我重复我的状态定义为是否可以使用以 i 结尾的子数组来生成 j。
#include<bits/stdc++.h>
using namespace std;
int DP[101][101];
int main()
{
int i,j,ans=INT_MIN;
int A[]={3,-1,2,-1,5,-3};
int N=sizeof(A)/sizeof(int);
for(i=1;i<=N;i++)
{
if(A[i-1]>=0)
DP[i][A[i-1]]++;
for(j=0;j<=100;j++)
{
if(DP[i-1][j])
{
if(j+A[i-1]>=0)
DP[i][j+A[i-1]]++;
}
if(DP[i][j])
ans=max(ans,j);
}
}
cout<<ans<<"\n";
return 0;
}
输出 8
我认为很难说这个算法到底是什么。
但是大部分书都把这个算法归类在DP部分,因为你结合了dp[n-1]的解来为dp[n]求解。
注意:我不明白你为什么使用这个版本的算法O(n^2)
您可以将此算法简化为 O(n)
curmax=0
sol=0
for x in array
curmax+=a[x]
if(curmax<0)curmax=0
if(curmax>sol)sol=curmax
我认为这是一个贪心算法,因为kadanes算法在每一步找到最大和然后找到整体解决方案。
Kadane 的是一种迭代动态规划算法。
优化迭代 DP 算法以沿算法进程的主轴删除 DP 矩阵的一维是很常见的。
例如,通常的'longest common subsequence'算法通常用二维矩阵描述,但如果算法从左到右进行,那么您实际上只需要space 2列。
Kadane 的算法是应用于一维问题的类似优化,因此整个 DP 数组都消失了。由于某种原因,您问题中的 DP 代码具有二维矩阵。我不知道为什么 -- 这真的没有意义。
这个网站很好地解释了推导:https://hackernoon.com/kadanes-algorithm-explained-50316f4fd8a6
正如算法导论中所定义的,“贪心算法总是做出当前看起来最好的选择。也就是说,它会做出局部最优选择,希望此选择将导致全局最优解。"
Kadane 的算法确实通过 current_sum = max(0, current_sum + x)
寻找局部最优解;同时,这也可以看作是 space 优化的动态规划解决方案 - dp[i]
仅依赖于 dp[i-1]
因此我们使用整数变量来保存 space。
所以我觉得DP的转换函数恰好是贪心的,看起来既是DP又是贪心的
Kadane 的算法既可以看作是贪心算法,也可以看作是 DP。如我们所见,我们保留了 运行 个整数和,当它小于 0 时,我们将其重置为 0(贪心部分)。这是因为继续使用负和比使用新范围重新开始更糟糕。现在它也可以看作是一个 DP,在每个阶段我们有 2 个选择:要么获取当前元素并继续之前的总和,要么重新开始一个新的范围。这两个选择都在实施中得到了照顾。
贪婪索尔
# Python program to find maximum contiguous subarray
# Function to find the maximum contiguous subarray
from sys import maxint
def maxSubArraySum(a,size):
max_so_far = -maxint - 1
max_ending_here = 0
for i in range(0, size):
max_ending_here = max_ending_here + a[i]
if (max_so_far < max_ending_here):
max_so_far = max_ending_here
if max_ending_here < 0:
max_ending_here = 0
return max_so_far
# Driver function to check the above function
a = [-13, -3, -25, -20, -3, -16, -23, -12, -5, -22, -15, -4, -7]
print "Maximum contiguous sum is", maxSubArraySum(a,len(a))
DP 太阳系
# Python program to print largest contiguous array sum
from sys import maxsize
# Function to find the maximum contiguous subarray
# and print its starting and end index
def maxSubArraySum(a,size):
max_so_far = -maxsize - 1
max_ending_here = 0
start = 0
end = 0
s = 0
for i in range(0,size):
max_ending_here += a[i]
if max_so_far < max_ending_here:
max_so_far = max_ending_here
start = s
end = i
if max_ending_here < 0:
max_ending_here = 0
s = i+1
print ("Maximum contiguous sum is %d"%(max_so_far))
print ("Starting Index %d"%(start))
print ("Ending Index %d"%(end))
# Driver program to test maxSubArraySum
a = [-2, -3, 4, -1, -2, 1, 5, -3]
maxSubArraySum(a,len(a))
我感觉Kadane的算法是最大子数组真动态规划解法的修改版problem.Why我感觉是这样吗? 我感觉是因为计算最大子数组的方式可以采取:
for(i=0;i<N;i++)
{
DP[i][A[i]]=true;
for(j= -ve maximum ;j<= +ve maximum ;j++)
if(DP[i-1][j])
DP[i][j+A[i]]=true;
}
如果可以用一个以 i-1 结尾的子数组形成 j 个元素 i 可以形成 j+A[i] 使用第 i 个元素并通过在第 i 个位置开始一个子数组单独形成 A[i] 最后我们可以在这个 DP 数组中搜索标记为 true 的最大值 j!
注意:DP[i][j]
表示是否可以使用以i结尾的子数组来生成j!这里我假设 j 也可以是负数。!现在可以很容易地得出 sum+ 一个负数 < sum 。这意味着添加任何负索引无助于获得更好的总和,这就是我们可以删除它们的原因!此外,我们关心最大 j 直到第 i-1
个位置,并将它与 i th
元素连接起来,这让我觉得这是一种贪婪的选择(只是因为最大值 + 元素给了我最大值)。
注意:我现在还没有研究过贪心算法,但我知道什么是贪心选择!
编辑:有人说我的算法没有任何意义所以我试图 post 我的代码让我自己清楚。我没有把 j 当作 -ve,因为它们没有成果。 我重复我的状态定义为是否可以使用以 i 结尾的子数组来生成 j。
#include<bits/stdc++.h>
using namespace std;
int DP[101][101];
int main()
{
int i,j,ans=INT_MIN;
int A[]={3,-1,2,-1,5,-3};
int N=sizeof(A)/sizeof(int);
for(i=1;i<=N;i++)
{
if(A[i-1]>=0)
DP[i][A[i-1]]++;
for(j=0;j<=100;j++)
{
if(DP[i-1][j])
{
if(j+A[i-1]>=0)
DP[i][j+A[i-1]]++;
}
if(DP[i][j])
ans=max(ans,j);
}
}
cout<<ans<<"\n";
return 0;
}
输出 8
我认为很难说这个算法到底是什么。
但是大部分书都把这个算法归类在DP部分,因为你结合了dp[n-1]的解来为dp[n]求解。
注意:我不明白你为什么使用这个版本的算法O(n^2)
您可以将此算法简化为 O(n)
curmax=0
sol=0
for x in array
curmax+=a[x]
if(curmax<0)curmax=0
if(curmax>sol)sol=curmax
我认为这是一个贪心算法,因为kadanes算法在每一步找到最大和然后找到整体解决方案。
Kadane 的是一种迭代动态规划算法。
优化迭代 DP 算法以沿算法进程的主轴删除 DP 矩阵的一维是很常见的。
例如,通常的'longest common subsequence'算法通常用二维矩阵描述,但如果算法从左到右进行,那么您实际上只需要space 2列。
Kadane 的算法是应用于一维问题的类似优化,因此整个 DP 数组都消失了。由于某种原因,您问题中的 DP 代码具有二维矩阵。我不知道为什么 -- 这真的没有意义。
这个网站很好地解释了推导:https://hackernoon.com/kadanes-algorithm-explained-50316f4fd8a6
正如算法导论中所定义的,“贪心算法总是做出当前看起来最好的选择。也就是说,它会做出局部最优选择,希望此选择将导致全局最优解。"
Kadane 的算法确实通过 current_sum = max(0, current_sum + x)
寻找局部最优解;同时,这也可以看作是 space 优化的动态规划解决方案 - dp[i]
仅依赖于 dp[i-1]
因此我们使用整数变量来保存 space。
所以我觉得DP的转换函数恰好是贪心的,看起来既是DP又是贪心的
Kadane 的算法既可以看作是贪心算法,也可以看作是 DP。如我们所见,我们保留了 运行 个整数和,当它小于 0 时,我们将其重置为 0(贪心部分)。这是因为继续使用负和比使用新范围重新开始更糟糕。现在它也可以看作是一个 DP,在每个阶段我们有 2 个选择:要么获取当前元素并继续之前的总和,要么重新开始一个新的范围。这两个选择都在实施中得到了照顾。
贪婪索尔
# Python program to find maximum contiguous subarray
# Function to find the maximum contiguous subarray
from sys import maxint
def maxSubArraySum(a,size):
max_so_far = -maxint - 1
max_ending_here = 0
for i in range(0, size):
max_ending_here = max_ending_here + a[i]
if (max_so_far < max_ending_here):
max_so_far = max_ending_here
if max_ending_here < 0:
max_ending_here = 0
return max_so_far
# Driver function to check the above function
a = [-13, -3, -25, -20, -3, -16, -23, -12, -5, -22, -15, -4, -7]
print "Maximum contiguous sum is", maxSubArraySum(a,len(a))
DP 太阳系
# Python program to print largest contiguous array sum
from sys import maxsize
# Function to find the maximum contiguous subarray
# and print its starting and end index
def maxSubArraySum(a,size):
max_so_far = -maxsize - 1
max_ending_here = 0
start = 0
end = 0
s = 0
for i in range(0,size):
max_ending_here += a[i]
if max_so_far < max_ending_here:
max_so_far = max_ending_here
start = s
end = i
if max_ending_here < 0:
max_ending_here = 0
s = i+1
print ("Maximum contiguous sum is %d"%(max_so_far))
print ("Starting Index %d"%(start))
print ("Ending Index %d"%(end))
# Driver program to test maxSubArraySum
a = [-2, -3, 4, -1, -2, 1, 5, -3]
maxSubArraySum(a,len(a))