我最近在一次采访中被问到这个问题,我仍然无法提出解决方案。
河里有N个插槽。给出阵列P,其中每个指数表示该位置处的石头将出现的时间。我必须想出一个算法来找到K个连续的空槽的最早时间。对于E.G。
N = 5
P = [2,5,1,4,3]
K = 2
Initially: [0,0,0,0,0]
All the slots are empty.
Now at:
Time t = 1, second stone will appear --> [0,1,0,0,0]
Time t = 2, fifth stone will appear --> [0,1,**0,0**,1]
Time t = 3, first stone will appear --> [1,1,0,0,1]
Time t = 4, fourth stone will appear --> [1,1,0,1,1]
Time t = 5, third stone will appear --> [1,1,1,1,1]
所以上述案例的答案是2
,因为在时间2
有(k = 2)个连续的空位。
答案 0 :(得分:5)
每次添加一块石头时,你基本上将一系列连续的空槽(零)分成两部分。您可以使用此构思构造二叉树,其中每个节点表示一个区间(零和一个 - 石头和空格),每个叶节点仅代表零区间
要添加石头,您会找到相应的叶子节点(相应的间隔必须包括新石头的位置)并添加新的叶子节点 - 左侧和右侧的间隔与您添加的石头的间隔。此时,您可以检查这些新间隔的长度,如果找到具有所需长度的间隔,则停止。
这里唯一的问题是树可能变得不平衡所以为了获得O(nlogn)最坏的情况你应该应用一些技术来平衡树的生长 - 红黑树或类似的东西 - https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree
答案 1 :(得分:2)
我终于在leetcode上找到了O(n)时间复杂度和O(n)空间复杂度解决方案。简要解释一下:
我们的想法是使用数组
days[]
来记录每个位置的花朵 盛开的一天。这意味着days[i]
是花朵盛开的一天 位置i+1
。我们只需要找到满足以下内容的子代days[left, left+1,...,left+k-1, right]
:对于任何i = left+1,..., left+k-1
,我们都可以days[left] < days[i] && days[right] < days[i]
。然后,结果为max(days[left], days[right])
。
以下是确切解决方案的链接:https://discuss.leetcode.com/topic/104771/java-c-simple-o-n-solution
答案 2 :(得分:1)
注意,在内部循环中,可以安全地省略i
位置右侧的P项。但是,这仍然是O(n ^ 2)
int K = 2;
int[] P = { 2, 5, 1, 4, 3 };
int N = P.Length;
for (int i = 0; i < N; i++)
{
for (int j = 0; j <= i; j++)
{
if (Math.Abs(P[j] - P[i] + 1) == K)
{
return i + 1; //+1 because we iterate from 0 | this is the ans (time)
}
}
}
答案 3 :(得分:0)
您可以使用BIT树来解决此问题。你想要k个槽是空的 所以我们假设发生在我的时间。
a=p[i]-k-1;
b=p[i]+k+1;
数组T告诉石头是否在索引i处。
现在,索引a和p [i]之间的所有条目或者数组T中的p [i]应该为零。这可以通过使用范围查询来检查我更喜欢BIT树,但也可以使用分段树。