给定一个1和0的数组,将数组分成若干部分,使得第一个数组中的1的数量等于另一个中的0的数量。 。打印发生此分区的索引。如果有很多这样的可能性,找到第一个这样的分区。
下面在python中给出了示例代码。它打印的答案是7.这意味着第一个数组直到a[7]
。第二个数组从a[8]
开始直到结束。
这个算法工作正常,但我认为复杂度是O(n ^ 2)。如果可能,我想要更好的解决方案。任何帮助都会很棒。
def findParts(arr):
length=len(arr)
count_ones = 0
count_zeros = 0
index=0
for index in range(length-1):
if arr[index] == 1:
count_ones+=1
for j in range(index+1, length-1):
if arr[j] == 0:
count_zeros+=1
if (count_ones-count_zeros == 0):
return index
else:
count_zeros=0;
a=[1,1,0,0,1,0,0,0,1,0,1,1,0,1,0,1,1]
print findParts(a)
答案 0 :(得分:4)
以下是线性时间算法,并证明了解决方案的存在以及该解决方案是唯一可行的解决方案:
lst = [1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1]
index = 0
leftCount, rightCount = 0, lst.count(0)
while leftCount < rightCount:
if lst[index] == 1:
leftCount += 1
else:
rightCount -= 1
index += 1
print(lst[:index], index, lst[index + 1:])
这将从索引0开始,左侧分区为空,在左侧分区0中计数为1。我们在O(n)中找到右侧分区中的0。
现在,我们迭代地将索引或分隔符向右移动。我们这样做,只要leftCount仍然低于rightCount。如果这发生了变化,我们就找到了解决方案(因为两个计数都是相同的)。当我们向右移动时,我们会查看list元素。如果它是1
,我们在左侧计数中添加一个;如果是0
,我们会从正确的计数中减去一个。最终,我们将达到两个计数相等的完美指数。
由于我们只是在每次迭代中更改一个计数,因此总会有这样的解决方案。而且,由于进一步迭代会使余额再次失效,这也证明只有单个解决方案。
至于时间复杂度,我们迭代列表一次以计算零,然后我们在移动边界时再次迭代它。所以这是O(n)。
答案 1 :(得分:1)
从分隔符位于中心元素开始,并计算数组左侧部分(#(1)
)的总数1和右侧部分的总数0( #(0)
)。
如果#(1) < #(0)
将分隔符向右移动一个元素并相应地更新#(0)
和#(1)
(基于前一个分隔符的值和新分隔符的值)。
如果#(1) > #(0)
移动分隔符,则会向左移动一个元素并相应地更新#(0)
和#(1)
。
您会在O(n)
找到分隔符。
您可以事先检查解决方案是否存在,以防止无限循环(如果没有解决方案,那么当数组全部为0时全部为1&#39; s。)
以下是代码:
import math
def findParts(arr):
length = len(arr)
index = int(math.ceil(length/2.0))
count_ones = arr[:index+1].count(1)
count_zeros = arr[index+1:].count(0)
if count_ones == 0 or count_ones == length:
return -1
while count_ones != count_zeros:
if count_ones < count_zeros:
index+=1
if arr[index] == 1:
count_ones+=1
else:
count_zeros-=1
else:
if arr[index] == 1:
count_ones-=1
else:
count_zeros+=1
index-=1
return index
a=[1,1,0,0,1,0,0,0,1,0,1,1,0,1,0,1,1]
print findParts(a)