Algorithm 两个等和数组中的最大跨度

Algorithm 两个等和数组中的最大跨度,algorithm,Algorithm,这是编程难题。我们有两个数组A和B。它们都只包含0和1 我们必须有两个指数i,j,这样 a[i] + a[i+1] + .... a[j] = b[i] + b[i+1] + ... b[j]. 我们还必须最大化i和j之间的差异。寻找O(n)溶液 我找到了O(n^2)解决方案,但没有得到O(n)这里有一个O(n)解决方案 我使用的事实是sum[I..j]=sum[j]-sum[I-1] 我保留每个找到的和的最左边的位置 int convertToPositiveIndex(int

这是编程难题。我们有两个数组A和B。它们都只包含0和1

我们必须有两个指数
i,j
,这样

 a[i] + a[i+1] + .... a[j] = b[i] + b[i+1] + ... b[j]. 
我们还必须最大化i和j之间的差异。寻找O(n)溶液

我找到了
O(n^2)
解决方案,但没有得到
O(n)
这里有一个
O(n)
解决方案

我使用的事实是
sum[I..j]=sum[j]-sum[I-1]

我保留每个找到的和的最左边的位置

    int convertToPositiveIndex(int index) {
        return index + N;
    } 

    int mostLeft[2 * N + 1];
    memset(mostLeft, -1, sizeof(mostLeft));

    int bestLen = 0, bestStart = -1, bestEnd = -1;

    int sumA = 0, sumB = 0;
    for (int i = 0; i < N; i++) {
        sumA += A[i];
        sumB += B[i];

        int diff = sumA - sumB;
        int diffIndex = convertToPositiveIndex(diff);

        if (mostLeft[diffIndex] != -1) {
            //we have found the sequence mostLeft[diffIndex] + 1 ... i
            //now just compare it with the best one found so far 
            int currentLen = i - mostLeft[diffIndex];
            if (currentLen > bestLen) {
                bestLen = currentLen;
                bestStart = mostLeft[diffIndex] + 1;
                bestEnd = i;
            }
        }

        if (mostLeft[diffIndex] == -1) {
            mostLeft[diffIndex] = i;
        }
    }

cout << bestStart << " " << bestEnd << " " << bestLen << endl;
int-convertToPositiveIndex(int索引){
返回指数+N;
} 
int mostLeft[2*N+1];
memset(mostLeft,-1,sizeof(mostLeft));
int-bestLen=0,bestStart=-1,bestEnd=-1;
int sumA=0,sumB=0;
对于(int i=0;ibestLen){
bestLen=当前Len;
bestStart=mostLeft[diffIndex]+1;
bestEnd=i;
}
}
if(mostLeft[diffIndex]=-1){
mostLeft[diffIndex]=i;
}
}

cout基本上,我的解决方案是这样的

使用一个变量来处理自开始以来的差异

int current = 0;
for index from 0 to length
    if a[i] == 0 && b[i] == 1
        current--;
    else if a[i] == 1 && b[i] == 0
        current++;
    else
        // nothing;
找到变量具有相同值的位置,这表示在这两个位置之间有相等的1和0


伪代码:

以下是我的主要解决方案:

int length = min (a.length, b.length);
int start[] = {-1 ... -1}; // from -length to length
start[0] = -1;
int count[] = {0 ... 0};   // from -length to length
int current = 0;
for (int i = 0; i < length; i++) {
    if (a[i] == 0 && b[i] == 1)
        current--;
    else if (a[i] == 1 && b[i] == 0)
        current++;
    else
        ; // nothing

    if (start[current] == -1) // index can go negative here, take care
        start[current] = current;
    else
        count[current] = i - start[current];
}
return max_in(count[]);
int length=min(a.长度,b.长度);
int start[]={-1…-1};//从头到尾
开始[0]=-1;
整数计数[]={0…0};//从头到尾
int电流=0;
for(int i=0;i
这是一个相当简单的O(N)解决方案:

int length = min (a.length, b.length);
int start[] = {-1 ... -1}; // from -length to length
start[0] = -1;
int count[] = {0 ... 0};   // from -length to length
int current = 0;
for (int i = 0; i < length; i++) {
    if (a[i] == 0 && b[i] == 1)
        current--;
    else if (a[i] == 1 && b[i] == 0)
        current++;
    else
        ; // nothing

    if (start[current] == -1) // index can go negative here, take care
        start[current] = current;
    else
        count[current] = i - start[current];
}
return max_in(count[]);
sa=[s1,s2,s3..sn]
其中
si=sum(a[0:i])
和类似的
sb

然后
sum(a[i:j])=sa[j]-sa[i]
sum(b[i:j])=sb[j]-sb[i]

注意,由于每次总和只增加1,我们知道
0最佳解是O(n)

首先让
c[i]=a[i]-b[i]
,然后问题变成查找i,j,其
和(c[i],c[i+1],…,c[j])=0
,和max
j-i

第二步让
d[0]=0
d[i+1]=d[i]+c[i],i>=0
,然后问题变成find i,j,其中
d[j+1]==d[i]
,max
j-i

d
的值在范围
[-n,n]
内,因此我们可以使用以下代码来找到答案

answer = 0, answer_i = 0, answer_j = 0
sumHash[2n + 1] set to -1
for (x <- 0 to n) {
  if (sumHash[d[x]] == -1) {
    sumHash[d[x]] = x
  } else {
    y = sumHash[d[x]]
    // find one answer (y, x), compare to current best
    if (x - y > answer) {
      answer = x - y
      answer_i = y
      answer_j = y
    }
  }
}
answer=0,answer\u i=0,answer\u j=0
sumHash[2n+1]设置为-1
对于(x个答案){
答案=x-y
答案i=y
答案_j=y
}
}
}

O(n)
O(n)
解决方案存在?请提供O(n^2)解决方案。它的复杂性可以通过优化一些步骤来降低。是的..但至少我们可以得到比O(n^2)更好的结果吗?@UmNyobe:为数组创建一个数组,每个索引都有和,然后对每个i,j进行迭代,并检查它是否合格。预处理(创建和)是O(n),用于检查所有对的是O(n^2)。请注意,可以使用和数组在O(1)中验证每一对。O(n^2)很容易…获取所有可能的连续对并计算和。具有最大和的索引将是答案。您能完成解决方案吗?在哪里打印答案?我已经完成了这个解决方案。这个答案不考虑序列在第一个数组元素中开始的条件。除非
mostLeft[diffIndex]!=1
,但随后分配了
bestStart
mostLeft[diffIndex]+1
。这使得0成为
bestStart
的不可能值。以两个数组{1},{1}作为示例输入来说明这个问题。不知道哪一个是第一个;)很好,“当前”计数器简化了事情。当我写我的文章时,我首先想到的是累积频率,尽管我们的解决方案会完全相同,或者说是很好的解释。我为理解解决方案的概念苦苦挣扎。