查找数组中元素的最大总和(带扭曲)

时间:2015-03-24 15:36:59

标签: algorithm logic kadanes-algorithm

给定一个带有+ ve和-ve整数的数组,找到最大总和,这样就不允许跳过2个连续的元素(即你必须至少选择其中一个元素才能继续前进)。

例如: -

10,20,30,-10,-50,40,-50,-1,-3

输出:10 + 20 + 30-10 + 40-1 = 89

12 个答案:

答案 0 :(得分:8)

使用动态编程方法可以解决这个问题。

arr 为给定数组, opt 为存储最佳解决方案的数组。 opt [i] 是从元素i开始可以获得的最大总和。

opt[i] = arr[i] + (some other elements after i)

现在要解决这个问题,我们向后迭代数组 arr ,每次都存储答案 opt [i] 。 由于我们不能跳过2个连续元素,因此必须包含元素i + 1 元素i + 2 opt [i]

因此对于每个我,opt[i] = arr[i] + max(opt[i+1], opt[i+2])

请参阅此代码以了解:

int arr[n];  // array of given numbers. array size = n.
nput(arr, n);   // input the array elements (given numbers)

int opt[n+2];   // optimal solutions. 
memset(opt, 0, sizeof(opt));    // Initially set all optimal solutions to 0.

for(int i = n-1; i >= 0; i--) {
    opt[i] = arr[i] + max(opt[i+1], opt[i+2]);
}

ans = max(opt[0], opt[1])   // final answer.

观察 opt 数组包含 n + 2 元素。这是为了避免在我们尝试访问 opt [i + 1] opt [i + 2] 时获取非法内存访问异常(内存超出范围)元素(n-1)

See the working implementation of the algorithm given above

答案 1 :(得分:6)

使用可以解决该问题的重复:

dp[i] = max(dp[i - 1] + a[i], <- take two consecutives
            dp[i - 2] + a[i], <- skip a[i - 1])

作为练习留下的基础案例。

答案 2 :(得分:2)

如果您看到+ ve整数,请将其添加到总和中。如果你看到一个负整数,那么检查下一个最大的整数选择并将其加到总和中。

10,20,30,-10,-50,40,-50,-1,-3

为此添加10,20,30,max(-10,-50),40 max(-50,-1),因为-3旁边没有元素丢弃它。

如果是+ ve,那么最后一个元素将会求和。

答案 3 :(得分:0)

答案:


我认为这个算法会有所帮助。

1.创建一个方法,给出输出特定用户输入数组的最大总和,如T [n],其中n表示总数。元素。
2.现在这个方法将继续添加数组元素,直到它们为正。因为我们想要最大化总和,并且没有必要放弃正面元素。
3.一旦我们的方法遇到负面元素,它就会将所有连续的负面元素转移到另一个创建新数组的方法,如N [i],这样该数组将包含我们在T [n]中遇到的所有连续负面元素。 ]并返回N [i]的最大输出。
通过这种方式,我们的主要方法不受影响,并且它继续添加正元素,并且每当遇到负元素时,它不是添加它们的实数值而是添加连续负元素数组的净最大输出。

例如:T [n] = 29,34,55,-6,-5,-4,6,43,-8,-9,-4,-3,2,78 //这里n = 14

主要方法工作:

29 + 34 + 55 +(从数组[-6,-5,-4]的辅助方法发送数据和获取值)+ 6 + 43 +(从数组的辅助方法发送数据&amp;获取值[-8, -9,-4,-3])+ 2 + 78
进程以最大输出终止。

二级方法工作:
{

N [i] =在需要时从Main方法或其自身获取数组。 这基本上是一种递归方法。
说N [i]有像N1,N2,N3,N4等元素。

对于i&gt; = 3:
现在选择就是这样。
1.如果我们取N1那么我们可以递归左关闭阵列,即N [i-1],它具有相同顺序的除N1之外的所有元素。这样净最大输出就是
N1 +(递归发送数据并从数组N [i-1]的辅助方法获取值)
2.如果我们不采用N1,那么我们就不能跳过N2。所以,现在算法就像第一选择,但从N2开始。所以在这种情况下最大输出将是
N2 +(递送数据并从数组N [i-2]的辅助方法中获取值)。 这里N [i-2]是包含除N1和N之外的所有N [i]个元素的数组。 N2以相同的顺序。
终止:当我们留下大小为1的数组(对于N [i-2])时,我们必须选择该特定值作为无选项。
递归最终将产生最大输出,我们必须最终选择更多的选择输出。 并将最大输出重定向到需要的位置。

对于i = 2:
我们必须选择更大的价值

对于i = 1:
我们当然可以跳过这个价值。
因此,在这种情况下,最大输出将为0。

}

答案 4 :(得分:0)

我认为这个答案会对你有帮助。

给定数组:

Given:- 10 20 30 -10 -50 40 -50 -1 -3

Array1:-10 30 60  50  10 90  40 89 86

Array2:-10  20 50  40  0  80  30 79 76

取最大值array1[n-1],array1[n],array2[n-1],array2[n] i.e 89(array1[n-1])

算法: -

  1. 对于array1值,请指定rray1[0]=a[0],array1=a[0]+a[1]array2[0]=a[0],array2[1]=a[1]
  2. 计算从2到n的array1值是array1[i-1]+a[i]array1[i-2]+a[i]之和的最大值。

    for loop from 2 to n{    
        array1[i]=max(array1[i-1]+a[i],array1[i-2]+a[i]);
    
    }
    
  3. 类似于array2从2到n的值是array2[i-1]+a[i]array2[i-2]+a[i].

    之和的最大值
    for loop from 2 to n{    
     array2[i]=max(array2[i-1]+a[i],array2[i-2]+a[i]);    
    }
    
  4. 最后找到array1[n-1],array[n],array2[n-1],array2[n];

    的最大值
       int max(int a,int b){      
       return a>b?a:b;    
       }
    
       int main(){    
       int a[]={10,20,30,-10,-50,40,-50,-1,-3};    
       int i,n,max_sum;    
       n=sizeof(a)/sizeof(a[0]);    
       int array1[n],array2[n];    
       array1[0]=a[0];    
       array1[1]=a[0]+a[1];    
       array2[0]=a[0];    
        array2[1]=a[1];    
    
        for loop from 2 to n{    
        array1[i]=max(array1[i-1]+a[i],array1[i-2]+a[i]);    
        array2[i]=max(array2[i-1]+a[i],array2[i-2]+a[i]);
    
        }    
           --i;
    
        max_sum=max(array1[i],array1[i-1]);    
        max_sum=max(max_sum,array2[i-1]);    
        max_sum=max(max_sum,array2[i]);    
    
         printf("The max_sum is %d",max_sum);    
          return 0;    
        } 
    
  5. Ans:max_sum是89

答案 5 :(得分:0)

public static void countSum(int[] a) {
        int count = 0;
        int skip = 0;
        int newCount = 0;

        if(a.length==1)
        {
            count = a[0];
        }
        else
        {
            for(int i:a)
            {
                newCount = count + i;
                if(newCount>=skip)
                {
                    count = newCount;
                    skip = newCount;
                }
                else
                {
                    count = skip;
                    skip = newCount;
                }
            }
        }
        System.out.println(count);
    }
}

答案 6 :(得分:0)

让数组的大小为N,索引为1 ... N

设f(n)为函数,它为子数组(1 ... n)的最大和提供答案,这样就不会有两个剩余的元素是连续的。

 f(n) = max (a[n-1] + f(n-2), a(n) + f(n-1))

在第一个选项中,即 - {a [n-1] + f(n-2)},我们将离开最后一个元素,并且由于所讨论的条件选择第二个最后一个元素。

在第二个选项中, - {a(n)+ f(n-1)}我们选择子数组的最后一个元素,因此我们可以选择/取消选择第二个最后一个元素。

现在从基础案例开始:

f(0) = 0   [Subarray (1..0) doesn't exist]

f(1) = (a[1] > 0 ? a[1] : 0);    [Subarray (1..1)]

f(2) = max( a(2) + 0, a[1] + f(1))   [Choosing atleast one of them]

继续前进,我们可以计算任何f(n),其中n = 1 ... N,并存储它们以计算下一个结果。是的,显然,案例f(N)将给我们答案。

Time complexity o(n)
Space complexity o(n)

答案 7 :(得分:0)

public static int sumz(int a[])
{
    int total=0;
    boolean isSkipped=false;
    for(int i=0;i<a.length;i++)
    {
        if(a[i]<0) // we check when value is less than 0
        {
            if(i+1<a.length) //to check next element we compare whether next element consist in array or not
            {
              if(a[i]>=a[i+1]||isSkipped) // here we check next element less than current element
              {
                  if(a[i]==a[i+1])  //if its equal to current than we check next to next element to decide this skip
                    {
                        if(i+2<a.length)
                        {
                            if(a[i+2]>a[i+1]) // here we check next to next element if its greater than next than we skip current element
                            {
                                isSkipped=true;
                            }else{
                                isSkipped=false; // or else we take current element
                                total=total+a[i];
                            }
                        }
                        else{
                            total=total+a[i];
                            isSkipped=false;
                        }
                    }
                    else{
                         isSkipped=false; // here if its bigger than next we take it and make isSkipped false as we didnt skipped the element
                        total=total+a[i];
                    }
              }
              else if(isSkipped) //if previous element is skipped than we have to take this elements
              {
                  total=total+a[i];
                  isSkipped=false;
              }
              else // if it failes all condition than we skip element
              {
                  isSkipped=true;
              }
            }
            else if(isSkipped==false && a[i]>0) //if its last element and last element is not skipped and its greater than 0 than we add it in total
            {
                total=total+a[i];
                isSkipped=false;
            }
        }
        else
        {
            isSkipped=false; // value which are greater than 0 are added directly
            total=a[i]+total;
        }
    }
    return total;
}

答案 8 :(得分:0)

n = arr.length()。 在数组末尾附加0以处理边界情况。 ans:大小为n + 1的int数组。 ans [i]将存储数组a [0 ... i]的答案,其中包括答案和中的[i]。 现在,

ans[0] = a[0]
ans[1] = max(a[1], a[1] + ans[0])
for i in [2,n-1]: 
   ans[i] = max(ans[i-1] , ans[i-2]) + a[i]

最终答案是[n]

答案 9 :(得分:0)

  

如果您想避免使用动态编程

  • 要找到最大金额,首先,您要添加所有正数 数字。
  • 我们只会跳过负面元素。既然我们不是 允许跳过2个连续元素,我们将把所有连续 临时数组中的负元素,可以计算出最大总和 使用如下定义的sum_odd_even函数的替代元素。

  • 然后我们可以将所有这些临时数组的最大值添加到我们的总和中 正数。最后的总和将为我们提供所需的输出。

代码:

def sum_odd_even(arr):
    sum1 = sum2 = 0
    for i in range(len(arr)):
        if i%2 == 0:
            sum1 += arr[i]
        else:
            sum2 += arr[i]
    return max(sum1,sum2)

input = [10, 20, 30, -10, -50, 40, -50, -1, -3]
result = 0
temp = []
for i in range(len(input)):
    if input[i] > 0:
        result += input[i]
    if input[i] < 0 and i != len(input)-1:
        temp.append(input[i])
    elif input[i] < 0:
        temp.append(input[i])
        result += sum_odd_even(temp)
        temp = []
    else:
        result += sum_odd_even(temp)
        temp = []

print result

答案 10 :(得分:0)

简单的解决方案:略过扭曲:)。如果连续-ve,只需跳过i&i + 1中最小的数字。有条件的话要检查直到n-2个元素,最后检查最后一个元素。

int getMaxSum(int[] a) {
    int sum = 0;
    for (int i = 0; i <= a.length-2; i++) {
        if (a[i]>0){
            sum +=a[i];
            continue;
        } else if (a[i+1] > 0){
            i++;
            continue;
        } else {
            sum += Math.max(a[i],a[i+1]);
            i++;
        }
    }
    if (a[a.length-1] > 0){
        sum+=a[a.length-1];
    }
    return sum;
}

答案 11 :(得分:0)

正确的复发如下:

dp[i] = max(dp[i - 1] + a[i], dp[i - 2] + a[i - 1])

第一种情况是我们选择第i个元素的情况。第二种情况是我们跳过第i个元素的情况。在第二种情况下,我们必须选择第(i-1)个元素。

IVlad答案的问题在于,它总是选择第i个元素,这可能导致答案不正确。