我只有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(比较指数差异)
所以继续前进,找到元素最少的元素......
我正在为此解决方案寻找更好的算法。
答案 0 :(得分:5)
我相信你可以通过滚动窗口来实现:
i
)。k
0(例如,窗口以索引j
结束)记录窗口长度(例如j-i+1=L
)。i
的最左边的0,并继续扫描,直到你获得下一个0(比如索引i'
j
的窗口的右端延伸至j'
,以便再次计算0 = k
。L'=j'-i'+1
较小,请更新它。继续重复上述过程,直到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)
有两个指示。
现在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的索引。