给定一个0和1的数组,找到最大子数组,使0和1的数量相等。
这需要在O(n)时间和O(1)空间中完成
我有一个算法,它在O(n)时间和O(n)空间中完成。它使用一个前缀和数组,并利用这样一个事实:如果0和1的数量相同,那么
sumOfSubarray=长度ThofSubarray/2
#包括<;iostream>;
#定义M 15
使用名称空间std;
void getSum(int arr[],int prefixsum[],int size){
int i;
前缀sum[0]=arr[0]=0;
前缀sum[1]=arr[1];
对于(i=2;i<;=size;i++){
前缀sum[i]=前缀sum[i-1]+arr[i];
}
}
无效查找(int a[],int&;start,int&;end){
while(开始<;结束){
int mid=(开始+结束)/2;
如果((结束-开始+1)==2*(a[结束]-a[开始-1]))
打破
如果((结束-开始+1)>;2*(a[结束]-a[开始-1])){
如果(a[开始]==0和a[结束]==1)
开始++;否则
结束--;
}否则{
如果(a[开始]==1和a[结束]==0)
开始++;否则
结束--;
}
}
}
int main(){
整数大小,arr[M],ps[M],开始=1,结束,宽度;
;
cin>;>;尺寸;
arr[0]=0;
结束=大小;
对于(int i=1;i<;=size;i++)
cin>;>;arr[i];
getSum(arr、ps、size);
查找(ps、开始、结束);
如果(开始!=结束)
不能<;<;(开始-1)<;“(结束-1)<;<;<;<;结束;否则不能<;<;<;<;“无解决方案”;
返回0;
}
现在我的算法是O(n)时间和O(Dn)空间,其中Dn是列表中的总不平衡。
此解决方案不会修改列表
设D为列表中1和0的差值
首先,让我们线性地遍历列表并计算D,看看它是如何工作的:
我将以这个列表为例:l=1100111100001110
元素D
空0
1 1
1.2<-
0 1
0 0
1 1
1 2
1 3
1 4
0 3
0 2
0 1
0 0
1 1
1 2
1 3
0.2<-
找到最长的平衡子阵相当于在D中找到两个相等的元素,它们距离较远。(在本例中,2 2用箭头标记。)
最长的平衡子阵列位于元素+1的第一次出现和元素的最后一次出现之间。(第一个箭头+1和最后一个箭头:00111100001110)
备注:
最长的子阵列将始终位于D的两个元素之间
介于[0,Dn]之间,其中Dn是D的最后一个元素。(在
上一个示例)Dn是系统中1s和0s之间的总不平衡
列表(如果Dn为负,则为[Dn,0]在这个例子中,这意味着我不需要“看”3s或4s
证明:
让Dn>0
如果存在由p(p>Dn)分隔的子数组。自0<;Dn<;P
在到达D的第一个元素,它等于P之前,我们到达一
元素等于Dn。因此,由于列表的最后一个元素等于Dn,因此由Dns分隔的子数组比由Ps分隔的子数组最长。因此,我们不需要查看Ps由于相同的原因,p不能小于0
对于Dn<;0
现在让我们研究D,D不是随机的,两个连续元素之间的差总是1或-1。在D和初始列表之间有一个简单的双射。因此,对于这个问题,我有两种解决方案:
- 第一种方法是跟踪每个产品的第一次和最后一次出现
D中介于0和Dn之间的元素(参见备注) - 第二种方法是将列表转换为D,然后处理D
第一个解决方案
目前,我找不到比第一种更好的方法:
首先计算Dn(以O(n)为单位)。Dn=2
第二,不是创建D,而是创建一个字典,其中键是D的值(介于[0和Dn]之间),每个键的值是一对(a,b),其中a是键的第一次出现,b是最后一次出现
元素D词汇表
空0{0:(0,0)}
1 1 {0:(0,0) 1:(1,1)}
1 2 {0:(0,0) 1:(1,1) 2:(2,2)}
0 1 {0:(0,0) 1:(1,3) 2:(2,2)}
0 0 {0:(0,4) 1:(1,3) 2:(2,2)}
1 1 {0:(0,4) 1:(1,5) 2:(2,2)}
1 2 {0:(0,4) 1:(1,5) 2:(2,6)}
1 3 { 0:(0,4) 1:(1,5) 2:(2,6)}
1 4 {0:(0,4) 1:(1,5) 2:(2,6)}
0 3{0:(0,4) 1:(1,5) 2:(2,6) }
0 2 {0:(0,4) 1:(1,5) 2:(2,9) }
0 1 {0:(0,4) 1:(1,10) 2:(2,9) }
0 0 {0:(0,11) 1:(1,10) 2:(2,9) }
1 1 {0:(0,11) 1:(1,12) 2:(2,9) }
1 2 {0:(0,11) 1:(1,12) 2:(2,13)}
1 3 {0:(0,11) 1:(1,12) 2:(2,13)}
0 2 {0:(0,11) 1:(1,12) 2:(2,15)}
您选择了差异最大的元素:2:(2,15)并且是l[3:15]=00111100001110(l=1100111100001110)
时间复杂性:
2个过程,第一个用于计算Dn,第二个用于构建
措辞。
在字典里找到最大值总数为0(n)
空间复杂性:
D:O(1)中的当前元素是词汇表O(Dn)
我不会因为这句话而把3和4放在毕业典礼上
复杂性是O(n)时间和O(Dn)空间(在平均情况下为Dn<;
n) .
我想,对于这种方法,可能有一种比用措辞更好的方法
欢迎提出任何建议
希望能有帮助
第二个解决方案(只是一个想法而不是真正的解决方案)
第二种方法是将您的列表转换为D(因为从D返回列表很容易)。(O(n)时间和O(1)空间,因为我就地变换列表,即使它可能不是“有效”的O(1))
然后从D开始,你需要找到2个相等的元素,它们距离我们越远
这看起来像是在链表中查找最长的循环,Richard Brent算法的修改可能会返回最长的循环,但我不知道如何执行,并且需要O(n)时间和O(1)空间
找到最长的周期后,返回第一个列表并打印它
该算法需要O(n)时间和O(1)空间复杂度