给定一个由0和1组成的数组,找到最大子数组,使得其中的0和1的数量相等。需要在O(n)时间复杂度和O(1)空间复杂度内完成。
我有一个算法可以在O(n)时间复杂度和O(n)空间复杂度内实现。它使用了前缀和数组,并利用了这样一个事实,即如果0和1的数量相同,则子数组的和=sumOfSubarray = lengthOfSubarray/2
#include<iostream>
#define M 15
using namespace std;
void getSum(int arr[],int prefixsum[],int size) {
int i;
prefixsum[0]=arr[0]=0;
prefixsum[1]=arr[1];
for (i=2;i<=size;i++) {
prefixsum[i]=prefixsum[i-1]+arr[i];
}
}
void find(int a[],int &start,int &end) {
while(start < end) {
int mid = (start +end )/2;
if((end-start+1) == 2 * (a[end] - a[start-1]))
break;
if((end-start+1) > 2 * (a[end] - a[start-1])) {
if(a[start]==0 && a[end]==1)
start++; else
end--;
} else {
if(a[start]==1 && a[end]==0)
start++; else
end--;
}
}
}
int main() {
int size,arr[M],ps[M],start=1,end,width;
;
cin>>size;
arr[0]=0;
end=size;
for (int i=1;i<=size;i++)
cin>>arr[i];
getSum(arr,ps,size);
find(ps,start,end);
if(start!=end)
cout<<(start-1)<<" "<<(end-1)<<endl; else cout<<"No soln\n";
return 0;
}
if(a[start]==0 && a[end]==1)
和if(a[start]==1 && a[end]==0)
这两行代码。这里的a
指的是前缀和数组;我相信您本意是引用原始数据。事实上,条件a[start]==1 && a[end]==0
是不可能的;因为start < end
且数组中没有负数元素,所以直到start
的前缀和不能大于直到end
的前缀和。 - Karthik Viswanathan