Kadane算法负数

时间:2012-03-30 11:40:57

标签: c++ algorithm kadanes-algorithm

int array[] = {-1, 4, -2, 5, -5, 2, -20, 6};

如果我有那个数组,我的Kadane算法实现找到最大的子数组:

  int max_so_far = INT_MIN;
  int max_ending_here = 0;
  for (int i = 0; i < size; i++) {
    max_ending_here = max(max_ending_here + array[i], 0);
    max_so_far = max(max_ending_here, max_so_far);
  }

  printf("%d\n", max_so_far);

但是,如果我有一系列所有底片:

int array[]= {-10, -10, -10};

它不起作用,它应该返回-10,但我得到0。

我怎样才能让它对负数起作用?

谢谢!

16 个答案:

答案 0 :(得分:36)

当所有元素都为负数时,最大子数组为空子数组,其总和为0.

但是如果你想在这种情况下改变算法以存储最大的元素,你可以执行以下操作:

int max_so_far      = INT_MIN;
int max_ending_here = 0;
int max_element     = INT_MIN;

for (int i = 0; i < size; i++)
{
    max_ending_here = max(max_ending_here + array[i], 0);
    max_so_far      = max(max_ending_here, max_so_far);
    max_element     = max(max_element, array[i]);
}

if (max_so_far == 0)
  max_so_far = max_element;

printf("%d\n", max_so_far);

答案 1 :(得分:17)

根据Wikipedia,Kadane的算法需要至少一个正数,因此您的所有负数组都是无效输入。

答案 2 :(得分:3)

对Kadane的算法略作补充。 取一个标志,are_all_elements_negative(设置为true)和一个int(存储最高的-ve整数) 迭代数组时,如果找到正数,则将标志设置为false。 当标志为true时,存储最高的-ve num。最后,检查标志,如果标志为真,则输出-ve整数,否则输出常规的Kadane算法输出。

答案 3 :(得分:1)

int max_so_far = INT_MIN;
int max_ending_here = array[0];
for (int i = 1; i < size; i++) {
    max_ending_here = max(max_ending_here + array[i], array[i]);
    max_so_far = max(max_ending_here, max_so_far);
 }
 printf("%d\n", max_so_far);

可能有效

答案 4 :(得分:1)

这是实现目标的另一种选择

int Solution::maxSubArray(const vector<int> &A){
    int cs=0,ms=0,l=A.size(),x=0,min;
    if(A[0]<0)
        min=A[0];
        x++;
    if(l==1)
        return A[0];
    for(int i=1;i<A.size();i++){
        if(A[i]<0)
            x++;
        if(A[i]>min)
            min=A[i];
        else
            break;
      }
    if(x==l)
        return min;
    for(int i=0;i<A.size();i++){
        cs=cs+A[i];
        if(cs<0)
        cs=0;
        ms=max(cs,ms);
    }
return ms;
}

答案 5 :(得分:0)

如果所有元素都是负数,则返回最小负数。 在所有其他情况下,您的解决方案都可以正常工作。

printf("%d\n",max(max_so_far, *max_element(array,array+size)) );

答案 6 :(得分:0)

当阵列的所有元素都是负数时,Kadane的算法不起作用。在这种情况下它只返回0。如果你想要处理这个,我们需要在实际实现之前添加额外的阶段。该阶段将查看所有数字是否为负数,如果它们将返回它们的最大值(或绝对值最小)。

我可以建议一个实现

#define find_max_val(x,y) x >= y ?x :y;

int min_sum(int a[],int n){
int min_so_far = a[0],min_end_here = a[0];

for(int i = 1;i < n; i++){

    min_end_here = find_max_val(a[i],min_end_here + a[i]);
    min_so_far = find_max_val(min_so_far,min_end_here);
}

return min_so_far;
}

还有其他实现取决于需要。

答案 7 :(得分:0)

我参加这个派对的时间已经很晚了,但是这样会有什么作用吗?:

cur_sum = max_sum = sequence[0];
sum_to_j = 0;
for j in range(0, len(sequence)):
    sum_to_j += sequence[j];
    if sum_to_j > cur_sum:
        cur_sum = sum_to_j;
    if cur_sum > max_sum:
        max_sum = cur_sum
    if sum_to_j < 0:
        sum_to_j = 0;
        cur_sum = sequence[j];
print max_sum;

答案 8 :(得分:0)

如果所有元素都是负数,则按值返回最大元素

    boolean allNegative = true;
    int bigNegative = Integer.MIN_VALUE;

    int maxSum = 0;
    int sum =  0;
    for(int i=0;i<a.size();i++){
        // if all numbers are negative
        if(a.get(i)>=0){
            allNegative = false;
        }else{
        if(a.get(i)>bigNegative){
            bigNegative = a.get(i);
        }

        }
    sum += a.get(i);
    if(sum<0){
        sum=0;
    }
    if(sum>maxSum){
        maxSum = sum;
    }

    }
    if(allNegative){
        return bigNegative;
    }
    return maxSum;

答案 9 :(得分:0)

它适用于以下代码。

public int algorithmKadane(int[] input_array){
int sum = input_array[0];
int rotate_sum = input_array[0];
for(int i=1; i< input_array.length ; i++){ 
rotate_sum = Math.max(input_array[i], rotate_sum+input_array[i]);
sum = Math.max(rotate_sum,sum);
}
return sum;
}

答案 10 :(得分:0)

请参阅wikiped kadane的算法max subarray

 int max_subArray(Integer[] input){
    int max_so_far,max_ending_here;
    max_so_far = max_ending_here =input[0];

    for(int i =1; i<input.length;i++){
        max_ending_here = Math.max(input[i], input[i]+max_ending_here);
        max_so_far = Math.max(max_so_far, max_ending_here);
    }

    return max_so_far;      
}

在你的情况下它将返回-10

答案 11 :(得分:0)

希望该解决方案对于Kadane的算法也能处理所有负数的情况

    long long int n,max_f=0,i,max_end=0,s;
    cin>>n;
    long long int a[n];
    for(i=0;i<n;i++)
    {
        cin>>a[i];
    }
    long long int *m;
    m=max_element(a,a+n);
    if(*m<0)
    {
        s=*m;

    }
    else {

        for(i=0;i<n;i++)
        {
            max_end= max_end +a[i];
            if(max_end<0)
            {
                max_end=0;
            }
            if(max_f < max_end)
            {
            max_f=max_end;
            }
            s=max_f;
        }
    }
    cout<<s<<endl;
}

答案 12 :(得分:0)

如果我们有一个所有负数的数组,那么数组中的max元素将是结果。
例如:如果数组元素是
-3 -2 -5 -4 -1

最大和子数组为-1。

我们可以添加此检查,看看函数Kadane的返回值是否为0。
(只是O(n)搜索。不会更改时间复杂度:))

代码:

int maxSubArraySum(int a[], int size) { 
    int max_so_far = INT_MIN, max_ending_here = 0, max_negative_scenario = INT_MIN; 

    for (int i = 0; i < size; i++) { 
        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; 

        if(a[i] > max_negative_scenario) // additional check
            max_negative_scenario = a[i];
    } 
    if(max_so_far == 0) // additional check
        max_so_far = max_negative_scenario;
    return max_so_far; 
} 

答案 13 :(得分:0)

根据WIKI

public int maxSubArray(int[] nums) {
    int currentSum = 0;
    int bestSum = 0;

    for (int element : nums) {
        currentSum = Math.max(0, currentSum + element);
        bestSum = Math.max(bestSum, currentSum);
    }

    return bestSum;
}

上面的代码对于输入将失败

nums = [-1]

根据WIKI again

如果输入不包含任何正数元素(包括当输入为空时),此版本的算法将返回0。对于不允许空子数组的问题变体,应将best_sum初始化为负无穷大,并且在for循环中,current_sum也应更新为max(x,current_sum + x)。在那种情况下,如果输入不包含正元素,则返回的值是最大元素的值(即最小负值),如果输入为空,则返回负无穷大。

修改后的否定输入代码:

public int maxSubArray(int[] nums) {
    int currentSum = 0;
    int bestSum = Integer.MIN_VALUE;

    for (int element : nums) {
        currentSum = Math.max(element, currentSum + element);
        bestSum = Math.max(bestSum, currentSum);
    }

    return bestSum;
}

答案 14 :(得分:-1)

        public static int max_sum(int[] in){

        int maxsum=0;
        int cursum=0;
        for (int i=0;i<in.length;i++){
            cursum = in[i]+cursum;
            if (cursum>maxsum) {
                maxsum = cursum;
            }

//            for negative value
            if (cursum < 0) {
                for (int n=0;n<in.length;n++){
                    maxsum = in[n];
                    if (cursum>maxsum){
                        maxsum=cursum;
                    }
                }
            }
        }
        return maxsum;
    }

答案 15 :(得分:-2)

我认为以下方法可行: -

int maxSub(vector<int> x){
    int sum=x[0],local_max=0;
    for(int i=0;i<x.size();i++){
        local_max+=x[i];
        if(sum < local_max)
            sum=local_max;
        if(local_max <0)
            local_max=0;
    }
return sum;

}