我在Codility Lessons上偶然发现了这个问题,这里是描述:
给出了由N个整数组成的非空零索引数组A.
三联体(X,Y,Z),使得0≤X<1。 Y&lt; Z&lt; N,称为双切片。
双切片之和(X,Y,Z)是A [X + 1] + A [X + 2] + ... + A [Y - 1] + A [Y + 1]的总和+ A [Y + 2] + ... + A [Z - 1]。
例如,数组A使得:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
包含以下示例双切片:
双切片(0,3,6),总和为2 + 6 + 4 + 5 = 17,
双切片(0,3,7),总和为2 + 6 + 4 + 5 - 1 = 16,
双切片(3,4,5),sum为0。
目标是找到任何双切片的最大总和。
写一个函数:
int solution(vector&amp; A);
给定由N个整数组成的非空零索引数组A,返回任意双切片的最大总和。
例如,给定:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
函数应该返回17,因为数组A的双片没有大于17的总和。
假设:
N是[3..100,000]范围内的整数; 数组A的每个元素都是[-10,000..10,000]范围内的整数。
复杂度:
预期的最坏情况时间复杂度为O(N); 预期的最坏情况空间复杂度是O(N),超出输入存储(不包括&gt;输入参数所需的存储)。
可以修改输入数组的元素。
我已经读过关于从索引i开始计算MaxSum并在索引i结束的算法,但我不知道为什么我的方法有时会产生不好的结果。想法是计算在索引i处结束的MaxSum,省略范围0..i处的最小值。这是我的代码:
int solution(vector<int> &A) {
int n = A.size();
int end = 2;
int ret = 0;
int sum = 0;
int min = A[1];
while (end < n-1)
{
if (A[end] < min)
{
sum = max(0, sum + min);
ret = max(ret, sum);
min = A[end];
++end;
continue;
}
sum = max(0, sum + A[end]);
ret = max(ret, sum);
++end;
}
return ret;
}
如果你能帮助我指出漏洞,我会很高兴的!
答案 0 :(得分:4)
我的解决方案基于双向Kadane算法。我的博客here上有更多详情。分数100/100。
public int solution(int[] A) {
int N = A.length;
int[] K1 = new int[N];
int[] K2 = new int[N];
for(int i = 1; i < N-1; i++){
K1[i] = Math.max(K1[i-1] + A[i], 0);
}
for(int i = N-2; i > 0; i--){
K2[i] = Math.max(K2[i+1]+A[i], 0);
}
int max = 0;
for(int i = 1; i < N-1; i++){
max = Math.max(max, K1[i-1]+K2[i+1]);
}
return max;
}
答案 1 :(得分:1)
这是我的代码:
int get_max_sum(const vector<int>& a) {
int n = a.size();
vector<int> best_pref(n);
vector<int> best_suf(n);
//Compute the best sum among all x values assuming that y = i.
int min_pref = 0;
int cur_pref = 0;
for (int i = 1; i < n - 1; i++) {
best_pref[i] = max(0, cur_pref - min_pref);
cur_pref += a[i];
min_pref = min(min_pref, cur_pref);
}
//Compute the best sum among all z values assuming that y = i.
int min_suf = 0;
int cur_suf = 0;
for (int i = n - 2; i > 0; i--) {
best_suf[i] = max(0, cur_suf - min_suf);
cur_suf += a[i];
min_suf = min(min_suf, cur_suf);
}
//Check all y values(y = i) and return the answer.
int res = 0;
for (int i = 1; i < n - 1; i++)
res = max(res, best_pref[i] + best_suf[i]);
return res;
}
int get_max_sum_dummy(const vector<int>& a) {
//Try all possible values of x, y and z.
int res = 0;
int n = a.size();
for (int x = 0; x < n; x++)
for (int y = x + 1; y < n; y++)
for (int z = y + 1; z < n; z++) {
int cur = 0;
for (int i = x + 1; i < z; i++)
if (i != y)
cur += a[i];
res = max(res, cur);
}
return res;
}
bool test() {
//Generate a lot of small test cases and compare the output of
//a brute force and the actual solution.
bool ok = true;
for (int test = 0; test < 10000; test++) {
int size = rand() % 20 + 3;
vector<int> a(size);
for (int i = 0; i < size; i++)
a[i] = rand() % 20 - 10;
if (get_max_sum(a) != get_max_sum_dummy(a))
ok = false;
}
for (int test = 0; test < 10000; test++) {
int size = rand() % 20 + 3;
vector<int> a(size);
for (int i = 0; i < size; i++)
a[i] = rand() % 20;
if (get_max_sum(a) != get_max_sum_dummy(a))
ok = false;
}
return ok;
}
实际解决方案是get_max_sum
函数(另外两个是强力解决方案和测试器函数,它生成随机数组并比较暴力和实际解决方案的输出,我将它们仅用于测试目的)。
我的解决方案背后的想法是计算一个子数组中的最大总和,该数组在i
之前的某个地方开始并以i - 1
结束,然后为了满足而做同样的事情(best_pref[i]
和best_suf[i]
,分别)。之后,我只是迭代所有i
并返回best_pref[i] + best_suf[i]
的最佳值。它正常工作,因为best_pref[y]
找到了固定x
的最佳y
,best_suf[y]
找到了固定z
的最佳y
且所有可能的y
检查{{1}}的值。
答案 2 :(得分:1)
def solution(A):
n = len(A)
K1 = [0] * n
K2 = [0] * n
for i in range(1,n-1,1):
K1[i] = max(K1[i-1] + A[i], 0)
for i in range(n-2,0,-1):
K2[i] = max(K2[i+1]+A[i], 0)
maximum = 0;
for i in range(1,n-1,1):
maximum = max(maximum, K1[i-1]+K2[i+1])
return maximum
def main():
A = [3,2,6,-1,4,5,-1,2]
print(solution(A))
if __name__ == '__main__': main()
答案 3 :(得分:0)
Ruby 100%
def solution(a)
max_starting =(a.length - 2).downto(0).each.inject([[],0]) do |(acc,max), i|
[acc, acc[i]= [0, a[i] + max].max ]
end.first
max_ending =1.upto(a.length - 3).each.inject([[],0]) do |(acc,max), i|
[acc, acc[i]= [0, a[i] + max].max ]
end.first
max_ending.each_with_index.inject(0) do |acc, (el,i)|
[acc, el.to_i + max_starting[i+2].to_i].max
end
end