Algorithm 两个等和数组中的最大跨度
这是编程难题。我们有两个数组A和B。它们都只包含0和1 我们必须有两个指数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
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
,和maxj-i
第二步让d[0]=0
,d[i+1]=d[i]+c[i],i>=0
,然后问题变成find i,j,其中d[j+1]==d[i]
,maxj-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}作为示例输入来说明这个问题。不知道哪一个是第一个;)很好,“当前”计数器简化了事情。当我写我的文章时,我首先想到的是累积频率,尽管我们的解决方案会完全相同,或者说是很好的解释。我为理解解决方案的概念苦苦挣扎。