昨天在Codechef上有一个在线编码事件,我无法弄清楚如何解决one of the questions from it。简单地说:
给出一个 N 号码列表{ a 1 , a 2 ,..., a N },找到范围[ L , R ](1≤ L ≤ R ≤ N )最大化总和( a 1 + ... + 一个 <子> L-1 子>) - (一 <子> →的子> + ... + 一 <子> - [R 子>)+(一 <子> - [R 1 子> + ... + 一 <子>名词子>)。
换句话说,您可以将列表的子部分乘以-1,并希望最大化结果列表的总和。
我查看了一些像this这样的解决方案,但无法弄清楚这家伙在做什么。
我该怎么做?
实施例
-2 3 -1 -4 -2
现在你可以将第3小节乘以3乘以得到
-2 3 1 4 2
这样sum(-2,3,1,4,2) = 8
是这种情况下可能的最大值
答案 0 :(得分:2)
如果我们能够找到数组中的最小序列而不是那个部分,如果我们乘以1会得到最大值。
例如,在此示例中:-2 3 -1 -4 -2
最小序列为-1,-4,-2。如果我们将这个序列乘以1,它将最大化总和。所以问题是如何找到最小和序列。
这是O(N)解决方案:
如果数组包含所有+ ve而不是没有需要乘以-1的子数组。检查以下问题。 minimum sum subarray in O(N) by Kadane's algorithm
答案 1 :(得分:0)
您显示的算法基本上计算了任何元素的最大总和和当前总和。
注意:它使用与原始元素相反的符号构建数组。
如果当前总和为负数,则它拒绝原始总和并开始与新元素的新总和。
如果当前总和是正数,那么这意味着包括前面的条目是有益的,它会将当前元素添加到总和中。
答案 2 :(得分:0)
如果我正确理解你的问题,听起来你想首先找到最小的子阵列,然后将其乘以-1并添加剩余的非否定值。
最小子阵列基本上与maximum subarray problem相反:
public class MaxSumTest {
public static class MaxSumList{
int s=0, e=0;
List<Integer> maxList;
public MaxSumList(List<Integer> l){
//Calculate s and e indexes
minSubarray(l);
//Negate the minSubarray
for(int i=s; i < e; i++)
l.set(i, -l.get(i));
//Store list
maxList = l;
}
public int minSubarray(List<Integer> l){
int tmpStart = s;
int currMin = l.get(0);
int globalMin = l.get(0);
for(int i=1; i<l.size(); i++){
if(currMin + l.get(i) > 0){
currMin = l.get(i);
tmpStart = i;
}
else{
currMin += l.get(i);
}
if(currMin < globalMin){
globalMin = currMin;
s = tmpStart;
e = i+1;
}
}
return globalMin;
}
}
public static void main(String... args){
MaxSumList ms = new MaxSumList(Arrays.asList(new Integer[]{-2, 3, -1, -4, -2}));
//Prints [-2, 3, 1, 4, 2]
System.out.println(ms.maxList);
}
}