我试图通过贪婪来做这件事:
一只小青蛙想要到达河的另一边。青蛙目前位于0号位置,想要到达位置X.树叶从树上掉落到河面上。
给出一个非空零索引数组A,由表示落叶的N个整数组成。 A [K]表示一片叶子在时间K下降的位置,以分钟为单位测量。
目标是找到青蛙可以跳到河的另一边的最早时间。只有当叶子出现在从1到X的河对岸的每个位置时,青蛙才能穿过。
写一个函数:
class Solution { public int solution(int X, int[] A); }
给定一个由N个整数和整数X组成的非空零索引数组A,返回青蛙可以跳到河的另一边的最早时间。
如果青蛙永远不能跳到河的另一边,那么该函数应该返回-1。
我的解决方案:
public int solution(int X, int[] A) {
int[] vDestT = new int[A.length];
int j = 0;
// find times where X is visited
// sort the array vDestT increasing order
for (int i = 0; i < A.length; i++) {
if (A[i] == X && i > X - 1) {
// put times corresponding to requested destination X in vDestT in an increasing order
if (j > 0 && i < vDestT[j - 1]) {
int temp = vDestT[j - 1];
vDestT[j - 1] = i;
vDestT[j] = temp;
} else
vDestT[j] = i;
j++;
}
}
int k = 0;
while (k < vDestT.length) {
int remainP = X - 1;
int remainT = vDestT[k] - 1;
// check A[0..X-1]
while (remainT >= remainP) {
if (A[remainT] < X) {
remainP--;
}
if (remainP == 0)
return vDestT[k];
remainT--;
}
if (remainT < remainP) {
k++;
continue;
}
}
return -1;
}
嗯,这是第一个出现在我脑海中的解决方案(获得18/100分)并希望改进它,所以我有一些问题: - 我应该用哪种结构替换 vDestT ?
- 我错过了什么条件(除了if(A.length<X) and if (A.length == 1 && X==1)
)?
修改 我以为我必须找到A [i] = X的所有时间,将&#34; i&#34; s放在一个排序的数组递增顺序中。从我命名为vDestT的那个数组的第一个元素开始,看看我是否可以在那之前得到所有的X-1位置,如果没有检查第二次A [i] = X. =&gt;一个非常复杂的方法,我不知道为什么我确信我应该得到A [i] = X的所有时间并对它们进行排序以便找到最早的时间。
答案 0 :(得分:3)
无需每个位置存储所有时间,然后对它们进行排序,因为您只对第一个感兴趣。此外,输入是按时间顺序排列的,因此您可能不需要一直检查到最后。
这样,您只需对输入进行一次迭代,并在X到N步骤中找到答案,即线性时间复杂度。
答案 1 :(得分:2)
你有一个数组A,它显然是一个按时间排序的元组(时间,位置)的集合。 填充所有索引在0和X之间的Set,并以方便的时间升序扫描Array,从集合中减去所看到的任何元素。当集合为空时,叶子的路径就完成了。你达到的时间点是最早可能的。 这需要线性时间和线性额外空间。
答案 2 :(得分:1)
由于此问题至少暂时标记为prolog,因此我认为可能对基于Prolog的解决方案感兴趣。请注意,使用适合约束的包,此方法对于基于Java的解决方案也可能有用!
我正在使用Prolog来说明总体思路:我将使用约束变量来跟踪 water 仍在流动的指数,即没有(还)被叶子覆盖。将变量的域视为代表河流的未覆盖的点。
最初,变量的域是整数1,2,3 ......,即所有整数I∈[1,∞)。我们称之为变量Water
。
假设对整数有适当的约束,我可以在Prolog中表达初始域:
Water in 1..sup
这意味着,最初,所有索引尚未涵盖。
我可以通过从变量的域中删除其索引来表明某个地点已被覆盖。
例如:
?- Water in 1..sup, Water #\= 3, Water #\= 7.
这使用了不平等约束,声明Water
不能再值3和7,因此我们将这些点视为覆盖通过叶子。对于上述查询,Prolog回答:
Water in 1..2\/4..6\/8..sup.
这只是一种更紧凑的方式来陈述完全相同的事情。
请注意,此类操作的时间复杂度取决于您的Prolog系统。例如,当从域中删除内部点时,GNU Prolog使用 bitvector 表示。这使得删除单个元素(摊销) O(1)操作!
现在仍然是系统地应用这种不平等约束,对于我们所有的位置,同时跟踪当前的指数。
解决方案可能如下所示:
minutes_to_x(Leaves, X, Min) :- Water in 1..sup, to_x(Leaves, X, Water, 1, Min). to_x([], _, _, _, -1). to_x([L|Ls], X, Water, Index0, Min) :- Water #\= L, ( fd_inf(Water, Inf), Inf #> X -> Min #= Index0 ; Index #= Index0 + 1, to_x(Ls, X, Water, Index, Min) ).
示例查询和答案:
?- minutes_to_x([1,3,2], 1, Min). Min = 1. ?- minutes_to_x([1,3,2], 2, Min). Min = 3. ?- minutes_to_x([1,3,2], 3, Min). Min = 3. ?- minutes_to_x([1,3,2], 4, Min). Min = -1.
这是一个关系,而不是一个函数,因此我们使用最后一个参数来保存分钟的数量。
只要X
的 infimum 大于Water
,青蛙就可以移动到X
位置,因为这意味着从1到1的所有点都会叶子<{1}} 涵盖。