如何找到可以分成两部分的二进制数组的最长切片:在左边部分,0应该是领导者;在正确的部分,1应该是领导者? 例如 : [1,1,0,1,0,0,1,1]应该返回7,因此第一部分是[1,0,1,0,0],第二部分是[1,1]
我尝试了以下soln并且在一些测试用例中取得了成功,但我认为它效率不高:
public static int solution(int[] A)
{
int length = A.Length;
if (length <2|| length>100000)
return 0;
if (length == 2 && A[0] != A[1])
return 0;
if (length == 2 && A[0] == A[1])
return 2;
int zerosCount = 0;
int OnesCount = 0;
int start = 0;
int end = 0;
int count=0;
//left hand side
for (int i = 0; i < length; i++)
{
end = i;
if (A[i] == 0)
zerosCount++;
if (A[i] == 1)
OnesCount++;
count = i;
if (zerosCount == OnesCount )
{
start++;
break;
}
}
int zeros = 0;
int ones = 0;
//right hand side
for (int j = end+1; j < length; j++)
{
count++;
if (A[j] == 0)
zeros++;
if (A[j] == 1)
ones++;
if (zeros == ones)
{
end--;
break;
}
}
return count;
}
答案 0 :(得分:5)
我同意蛮力是时间复杂度:O(n ^ 3)。
但这可以在线性时间内解决。我在C中实现了它,这里是代码:
int f4(int* src,int n)
{
int i;
int sum;
int min;
int sta;
int mid;
int end;
// Find middle
sum = 0;
mid = -1;
for (i=0 ; i<n-1 ; i++)
{
if (src[i]) sum++;
else sum--;
if (src[i]==0 && src[i+1]==1)
{
if (mid==-1 || sum<min)
{
min=sum;
mid=i+1;
}
}
}
if (mid==-1) return 0;
// Find start
sum=0;
for (i=mid-1 ; i>=0 ; i--)
{
if (src[i]) sum++;
else sum--;
if (sum<0) sta=i;
}
// Find end
sum=0;
for (i=mid ; i<n ; i++)
{
if (src[i]) sum++;
else sum--;
if (sum>0) end=i+1;
}
return end-sta;
}
此代码经过测试:暴力结果与此功能相对应。他们有相同的结果。我测试了10个元素(1024种组合)的所有有效数组。
如果您喜欢这个答案,请不要忘记投票:)
答案 1 :(得分:3)
正如所承诺的那样,继续更新:
我找到了一个简单的线性时间复杂算法来解决这个问题。
数学: 将输入定义为int []位,我们可以定义此函数:
f(x) = {bits[x] = 0: -1; bits[x] = 1: 1}
下一步是为给定的输入创建此函数的基本积分:
F(x) = bits[x] + F(x - 1)
F(-1) = 0
This integral is from 0 to x.
F(x)
只代表count(bits , 1 , 0 , x + 1) - count(bits , 0 , 0 , x + 1)
的数量。这可用于定义以下函数:F(x , y) = F(y) - F(x)
,它与count(bits , 1 , x , y + 1) - count(bits , 0 , x , y + 1)
相同(1的数量减去[x,y]范围内的0的数量 - 这只是为了说明如何算法基本上有效)。
由于搜索到的字段序列必须满足以下条件:在[start , mid]
范围内0必须是前导,并且在[mid , end]
范围内1必须是前导且end - start + 1
必须是搜索到的mid
最大可能值必须满足以下条件:F(mid) < F(start) AND F(mid) < F(end)
。因此,第一步是搜索“F(x)”的最小值,这将是中间值(每个其他点必须>>最小值,因此将导致更小/同样大的范围[end - start + 1]
。注意:此搜索可以通过考虑以下因素进行优化:f(x)
始终为1
或-1
。因此,如果f(x)
为下一个{{1}返回1位1}}步骤,具有最小值的下一个可能索引将是n
(自上一个最小值意味着'n'1s,之后需要'n'-1s才能达到最小值 - 或至少'n'个步骤)。
给定n * 2
的最小值为'x',我们可以简单地找到F(x)
和start
(最大/最小值b,s∈[0,长度(位) - 1]这样:end
和F(s) > F(mid)
,可以在线性时间内找到。
伪代码:
F(b) > F(mid)