算法:找到包含K 0的最小连续数组,其数组为1和0

时间:2012-12-06 10:26:48

标签: arrays algorithm data-structures

我只有1和0的数组。现在我想找到最小的连续子集/子阵列,其中至少包含K 0。

实施例 数组是1 1 0 1 1 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 和K(6)应为0 0 1 0 1 1 0 0 0或0 0 0 0 1 0 1 1 0 ....

我的解决方案

     Array: 1 1 0 1 1 0 1 1 0  0  0  0  1  0  1  1  0  0  0   1  1  0  0
     Index: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19  20 21 22 23
     Sum:   1 2 2 3 4 4 5 6 6  6  6  6  7  7  8  9  9  9  9  10 11 11 11
Diff(I-S):  0 0 1 1 1 2 2 2 3  4  5  6  6  7  7  7  8  9 10  10 10 11 12

对于K(6)

从9-15开始=在差异中存储差异

接下来增加差异 8-15(指数差异) 8-14(比较指数差异)

所以继续前进,找到元素最少的元素......

我正在为此解决方案寻找更好的算法。

4 个答案:

答案 0 :(得分:5)

我相信你可以通过滚动窗口来实现:

  1. 在给定的数组中,找到第一个出现的0(比如索引i)。
  2. 继续扫描,直到您的窗口中包含k 0(例如,窗口以索引j结束)记录窗口长度(例如j-i+1=L)。
  3. 现在,丢弃索引为i的最左边的0,并继续扫描,直到你获得下一个0(比如索引i'
  4. 将位于j的窗口的右端延伸至j',以便再次计算0 = k
  5. 如果新窗口长度L'=j'-i'+1较小,请更新它。

  6. 继续重复上述过程,直到j到达数组末尾。

    无需额外空间且时间复杂度为O(N),因为元素最多扫描两次。

答案 1 :(得分:1)

使用额外的O(k)内存,你可以在O(n)时间内完成。这是java代码。你正在做的是,如果a [i] == 0那么你检查队列的第一个元素指向。如果位置差异小于最小值,则更新答案。

Queue<Integer> queue =new LinkedList<Integer>();
int i=0;
while(queue.size()<k&&i<n)
{
if(a[i]==0)
{
queue.add(i);
}
i++;
}
if(i==n&&queue.size()<k)
System.out.println("Insufficient 0''s");
int ans=i-1-queue.peek();
for(int j=i;j<n;j++)
{
if(a[i]==0)
{
queue.poll();
queue.add(i);
ans=Math.min(ans,i-queue.peek());
}
}
System.out.println(ans);

编辑:解释

我们维护一个队列,该队列包含所有具有0的位置,并且我们将队列大小限制为k。所以最初在while循环中我们用前k个索引填充队列。如果在看到所有元素之后队列大小小于k,那么这是不可能的。在那之后,我们继续前往所有剩余的元素。每次我们看到0,我们计算子序列的长度,(i-queue.peek())并找到最小值。同样我们删除第一个元素,并且再次添加最新索引,保持队列大小

答案 2 :(得分:1)

完全正常工作的python代码:

>>> A = "1 1 0 1 1 0 1 1 0  0  0  0  1  0  1  1  0  0  0   1  1  0  0".split()
>>> A = map(int, A)
>>> zero_positions = [i for i, x in enumerate(A) if x == 0]
>>> k = 3
>>> containing_k_zeros_intervals = zip(zero_positions, zero_positions[k:])
>>> min(b - a for a, b in containing_k_zeros_intervals)
3

答案 3 :(得分:0)

  1. 从开始扫描数组,找到索引,直到我们得到k零。
  2. 有两个指示。

    现在ptr1位于看到第一个零的索引处。 start = ptr1

    ptr2位于我们找到k 0的索引处。

    end = ptr2;  a)增加ptr1。

    b)从ptr2 + 1找到索引,直到找到k 0为止。

    c)在ptr3说我们找到K 0。如果ptr3-ptr1&lt; (end-start)更新索引的开始和结束。

    重复步骤a -c直到列表的末尾。

    最后,start和end将有k 0的索引。