两个排序数组的最大总和

时间:2012-01-07 09:01:15

标签: c++ algorithm

您将获得两个排序的整数数组,它们具有一些常见的整数。两个序列之间的任何公共整数构成交叉点。 您可以从任何数组开始遍历并切换到另一个数组,也可以在交叉点继续使用相同的数组。 目标是找到产生最大数据总和的路径。 以下面两个序列为例,其中交叉点以粗体显示: 第一= 3 5 7 9 20 25 30 40 55 56 57 60 62 秒= 1 4 7 11 14 25 44 47 55 57 100

在上面的例子中,最大可能总和是450,这是添加的结果 3,5,7,9,20,25,44,47,55,56,57,60和62

我编写了以下代码,但它没有编译,请帮助:

/* M: size of the array a
   N: size of the array b
*/


int i,j,sum1,sum2,sum,m_i,n_j = 0;

void printIntersectionElements(int *a,int M, int *b, int N) {

    if (M == 0)
        return (b);
    if (N ==0)
        return(a);
    while( i < M &&  j < N ){
        sum1 = sum1 +a[i];
        sum2 = sum2 + b[j];
        if(a[i] == b[j]) { // found a common element.

            if(sum1>= sum2){
                for(;m_i<= i; m_i++)
                cout<< a[m_i];
                sum = sum +sum1; 
                m_i = i+1;
            }
            else {
                for(;n_j<= j; n_j++)
                cout<< b[n_j];
                sum = sum+sum2; 
                n_j = j+1;
            }
            sum1 = sum2 = 0;
        }
        i++;
        j++;
    }

}

3 个答案:

答案 0 :(得分:2)

您正尝试从使用void返回类型声明的函数返回结果。这不是有效的C ++,这就是你得到编译器错误的原因。

也可能存在其他错误。阅读错误消息:他们会告诉您问题的确切位置和位置。

答案 1 :(得分:2)

这个问题可以用O(m + n)来解决。 您可以为两个阵列维护累积和数组。 首先在O(m + n)中找到交点。 然后检查哪个数组在两个交点之间有最大总和。 将它们添加到变量中。 这是代码。

#include <iostream>
#include <vector>
#include <cstdio>

using namespace std;

void print(int a[], int x, int y) {
    for(int i = x; i <= y; i++) {
        printf("%d ", a[i]);
    }
}

int main ()
{
    int i, j, x, y, n, m;
    int a0[100], a1[100], sum1[100], sum0[100];
    vector <int> v0, v1;
    cout << "Enter the value of n and m:\n";
    cin >> n >> m;
    scanf("%d", &a0[0]);
    sum0[0] = a0[0];
    for(i = 1; i < n; i++) {
        scanf("%d", &a0[i]);
        sum0[i] = a0[i] + sum0[i-1];    //cumulative sum for first array
    }
    scanf("%d", &a1[0]);
    sum1[0] = a1[0];
    for(i = 1; i < m; i++) {
        scanf("%d", &a1[i]);
        sum1[i] += a1[i] + sum1[i-1];   //cumulative sum for second array
    }
    i = 0;
    j = 0;
    while(i < n && j < m) {    //loop breaks when either one of the array ends
        if(a0[i] == a1[j]) {   //if there is a intersection
            v0.push_back(i);   //store index of both the arrays
            v1.push_back(j);
            i++;
            j++;
        }
        else if(a0[i] > a1[j]) {   //else increase the index of array 
            j++;                   //containing small number
        }
        else if(a0[i] < a1[j]) {
            i++;
        }
    }
    i = 0;
    j = 0;
    int sum = 0;
    while(i < v0.size()) {
        x = v0[i];
        y = v1[i];
        if(i == 0) {
            if(sum0[x] > sum1[y]) { //check which array has greater sum
                sum += sum0[x];     //first intersection
                print(a0, 0, x);
            }
            else {
                sum += sum1[y];
                print(a1, 0, y);
            }
            i++;
        }
        else {
            if(sum0[x]-sum0[v0[i-1]] > sum1[y]-sum1[v1[i-1]]) {
                sum += sum0[x]-sum0[v0[i-1]]; //checks which array has greater sum
                print(a0, v0[i-1]+1, x);      //between two intersectio
            }
            else {
                sum += sum1[y]-sum1[v1[i-1]];
                print(a1, v1[i-1]+1, y);
            }
            i++;
        }
    }
    if(sum0[n-1]-sum0[x] > sum1[m-1]-sum1[y]) {
        sum += sum0[n-1]-sum0[x];   //check which array has greater sum
        print(a0, x+1, n-1);        //at last intersection
    }
    else {
        sum += sum1[m-1]-sum1[y];
        print(a1, y+1, m-1);
    }
    cout << endl << "sum = " << sum << endl;
    return 0;
}

答案 2 :(得分:1)

您的代码有几个问题:

首先它没有编译,因为你的函数被声明为返回void,但是你尝试返回int*。将您的退货声明更改为return;

但即使你修复了你的功能并没有解决你所描述的问题。

  • 当你到达两个数组中较小的数组的末尾时,你的求和就会停止。但是从你的例子中你应该直到两个数组的末尾。
  • 此外,当两个数组在同一位置包含相同的数字时,您只检测交叉点,但是从您的文本中我认为您应该将点检测为交叉点,即使它们位于数组中的不同位置(我可能是虽然错了,取决于你的运动的确切表述)。要做到这一点,最简单的方法是每次迭代只处理a[i]b[j]的较小值(并且只增加ij(如果它是交集)。