循环缓冲区中的最大连续总和

发布于 2024-11-08 13:08:29 字数 93 浏览 0 评论 0原文

我有一个程序来确定数组中最大的连续总和,但希望将其扩展为使用圆形数组。有没有比将单个数组加倍并调用我的函数来查找 2n 长度数组中所有 n 长度数组的最大总和更简单的方法?

I have a program to determine the largest contiguous sum in an array, but want to extend it to work with circular arrays. Is there an easier way to do that than doubling the single array and calling my function to find the largest sum over all n-length arrays in the 2n length array?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

む无字情书 2024-11-15 13:08:29

请参阅以下链接:

它使用 Kadane 算法解决了问题。

See the following link :

It solves a problem using Kadane Algorithem.

http://www.geeksforgeeks.org/maximum-contiguous-circular-sum/

青朷 2024-11-15 13:08:29

我认为@spinning_plate 的解决方案是错误的。请您针对给定的情况进行测试。

int arr[] = {-3, 6, 2, 1, 7, -8, 13, 0};

你的方法返回21。

实际的解决方案可以从第6个索引(即13值)开始..到第4个索引(即7值)结束。由于数组是循环的,我们可以从第 6 个索引到第 7 个索引以及从第 0 个索引到第 4 个索引获取连续序列。

上述案例的实际答案是:26

I think the solution by @spinning_plate is wrong. Ca you please test it for the given cases.

int arr[] = {-3, 6, 2, 1, 7, -8, 13, 0};

Your approach returns 21.

Actual solution can be start from 6th index(i.e. 13 value) .. and end to 4th index(i.e. 7 value). Since array is circular we can take continuous series from 6th index to 7th index and from 0th index to 4th index.

The actual answer for the above case is : 26

心安伴我暖 2024-11-15 13:08:29

好吧,您实际上不必将数组加倍。您可以通过对现有数组进行索引模 n 来模拟它,或者仅对其进行迭代两次。根据数组的大小和缓存行为,这最多应该比非循环数组的算法慢两倍。

Well, you don't have to actually double the array. You can just emulate it by indexing your existing array modulo n, or by just iterating over it twice. Depending on the size of your array and cache behavior, this should be at most a factor of two slower than the algorithm for the noncircular array.

脸赞 2024-11-15 13:08:29

对于给定的问题,
我们将应用kadane算法,我们还将找到具有最大负值的子集。如果删除最大负值,则将以循环顺序给出剩余数组的总和。如果该总和大于最大总和,则最大总和将按循环顺序求和。
该算法的复杂度为 O(n)。

Eg:- arr[i]={10,-3,-4,7,6,5,-4,-1}
      Ans:  max_sum=7+6+5+(-4)+(-1)+10
            Removed_set={-3,-4}
int find_maxsum(int arr[],int n)
{
 int i=0;
 int total=0;
 int maxa=0;
 int mini=0;
 int min_sum=0;
 int max_sum=0;


 while(i<n) 
  {
    maxa=maxa+arr[i];
    total=total+arr[i];
    mini=mini+arr[i];

   if(maxa>max_sum)
     max_sum=maxa; 
   if(mini<min_sum)
     min_sum=mini;
   if(maxa<0)
     maxa=0;
   if(mini>=0)
    mini=0;
}
if(total-min_sum>max_sum)
   max_sum=total-min_sum;
 return max_sum;

}

For the given problem,
We will apply kadane algorithm and we will also find the subset which will have maximum negative value.If the maximum negative value is removed that will give the sum of the remaining array in circular order.If that sum is greater than maximum sum then maximum sum will be sum in circular order.
Complexity for the algorithm is O(n).

Eg:- arr[i]={10,-3,-4,7,6,5,-4,-1}
      Ans:  max_sum=7+6+5+(-4)+(-1)+10
            Removed_set={-3,-4}
int find_maxsum(int arr[],int n)
{
 int i=0;
 int total=0;
 int maxa=0;
 int mini=0;
 int min_sum=0;
 int max_sum=0;


 while(i<n) 
  {
    maxa=maxa+arr[i];
    total=total+arr[i];
    mini=mini+arr[i];

   if(maxa>max_sum)
     max_sum=maxa; 
   if(mini<min_sum)
     min_sum=mini;
   if(maxa<0)
     maxa=0;
   if(mini>=0)
    mini=0;
}
if(total-min_sum>max_sum)
   max_sum=total-min_sum;
 return max_sum;

}

决绝 2024-11-15 13:08:29

我假设您使用的是 O(n) 算法,该算法继续添加总和,跟踪最大值,仅当总和为负数时才重新启动。要捕获圆形数组的情况,您唯一需要做的就是将相同的原理应用于圆形方面。当您到达原始算法中的数组末尾时,继续循环到开头,直到低于最大值或达到当前范围的开头(但我认为这是不可能的,因为如果解决方案是完整数组,我们应该在第一次通过时就看到了这一点),在这种情况下你就完成了。

max_start=0; max_end =0; maxv = 0; sum 0;
for i in range(arr):
    sum+= arr[i];
    if sum<0:
       sum=0; max_start =i;
    if maxv<sum:
       maxv=sum; max_end = i;

#seocnd pass
for i in range(max_start):
    sum+= arr[i];
    if sum<0:
       break;
    if maxv<sum:
       maxv=sum;max_end = i;

I assume you are using the O(n) algorithm that continues adding to the sum, keeping track of the maximum, only restarting if you sum to a negative number. The only thing you need to do to capture the case of circular arrays is to apply the same principle to the circular aspect. When you reach the end of the array in the original algorithm, keep looping around to the start until you go below the maximum or hit the beginning of the current range (I think this is impossible, though, because if the solution was the full array, we sould have seen this on the first pass), in which case you're done.

max_start=0; max_end =0; maxv = 0; sum 0;
for i in range(arr):
    sum+= arr[i];
    if sum<0:
       sum=0; max_start =i;
    if maxv<sum:
       maxv=sum; max_end = i;

#seocnd pass
for i in range(max_start):
    sum+= arr[i];
    if sum<0:
       break;
    if maxv<sum:
       maxv=sum;max_end = i;
┈┾☆殇 2024-11-15 13:08:29

基于 nikhil 的想法的正确代码:最小总和的元素子数组不能出现在最终的包装或不包装最大和子数组中。

public int maxSum(int[] arr) {
    if (arr.length == 0) return 0;

    int sum = 0;
    int min = Integer.MAX_VALUE;
    int eix = 0;
    for (int i = 0; i < arr.length; i++) {
        sum = sum + arr[i] < arr[i] ? sum + arr[i] : arr[i];
        if (sum < min) {
            min = sum;
            eix = i;
        }
    }
    int max = 0;
    sum = 0;
    for (int i = eix; i < arr.length + eix; i++) {
        int ix = i < arr.length ? i : i - arr.length;
        sum = sum + arr[ix] > arr[ix] ? sum + arr[ix] : arr[ix];
        max = max > sum ? max : sum;
    }

    return max;
}

Correct code based on nikhil's idea: elements of the minimum sum sub-array cannot appear in the final wrapping-or-not maximum sum sub-array.

public int maxSum(int[] arr) {
    if (arr.length == 0) return 0;

    int sum = 0;
    int min = Integer.MAX_VALUE;
    int eix = 0;
    for (int i = 0; i < arr.length; i++) {
        sum = sum + arr[i] < arr[i] ? sum + arr[i] : arr[i];
        if (sum < min) {
            min = sum;
            eix = i;
        }
    }
    int max = 0;
    sum = 0;
    for (int i = eix; i < arr.length + eix; i++) {
        int ix = i < arr.length ? i : i - arr.length;
        sum = sum + arr[ix] > arr[ix] ? sum + arr[ix] : arr[ix];
        max = max > sum ? max : sum;
    }

    return max;
}
末が日狂欢 2024-11-15 13:08:29

即使所有数字均为负数,例如 {-1, -2, -3},此代码也会返回正确答案。
将返回-1;

 public static int maxSubarraySumCircular(int[] A) {

    int maxSum = Arrays.stream(A).max().getAsInt();
    if (maxSum < 0)
        return maxSum;

    int maxKadane = KadaneAlgorithm(A);
    int maxWrap = 0;
    for (int i = 0; i < A.length; i++) {
        maxWrap += A[i];
        A[i] = -A[i];
    }
    maxWrap = maxWrap + KadaneAlgorithm(A);

    return maxWrap > maxKadane ? maxWrap : maxKadane;
}

private static int KadaneAlgorithm(int[] A) {
    int maxSoFar = 0;
    int maxEndingHere = 0;
    for (int i = 0; i < A.length ; i++) {

        maxEndingHere = maxEndingHere + A[i];

        if (maxEndingHere < 0 )
            maxEndingHere = 0;

        if(maxSoFar < maxEndingHere)
            maxSoFar = maxEndingHere;
    }

    return maxSoFar;
}

This code returns the correct answer even if all numbers are negative e.g., {-1, -2, -3}.
will return -1;

 public static int maxSubarraySumCircular(int[] A) {

    int maxSum = Arrays.stream(A).max().getAsInt();
    if (maxSum < 0)
        return maxSum;

    int maxKadane = KadaneAlgorithm(A);
    int maxWrap = 0;
    for (int i = 0; i < A.length; i++) {
        maxWrap += A[i];
        A[i] = -A[i];
    }
    maxWrap = maxWrap + KadaneAlgorithm(A);

    return maxWrap > maxKadane ? maxWrap : maxKadane;
}

private static int KadaneAlgorithm(int[] A) {
    int maxSoFar = 0;
    int maxEndingHere = 0;
    for (int i = 0; i < A.length ; i++) {

        maxEndingHere = maxEndingHere + A[i];

        if (maxEndingHere < 0 )
            maxEndingHere = 0;

        if(maxSoFar < maxEndingHere)
            maxSoFar = maxEndingHere;
    }

    return maxSoFar;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文