给出一个String数组,查找“ 最短索引范围”的大小,该大小查找所有唯一路径都通过了。
示例A = { E, R, E, R, A, R, T, A }
,应为 5 。如我们所见,A[2] = E and A[6] = T
的范围包含所有唯一路径。 (在这种情况下,E,R,A,T)
我可以用下面的多重循环来解决。 (由Kotlin解决。)
fun problem(array: Array<String>): Int {
if (array.isEmpty()) return 0
val unique = array.distinct()
var result = 200000
for (i in 0 until A.size) {
val tempSet = HashSet<String>()
val remaining = A.sliceArray(i until array.size)
var count = 0
while (true) {
tempSet.add(remaining[count])
if (unique.size == tempSet.size) break
count++
if (count == remaining.size) {
count = 200000
break
}
}
result = Math.min(result, count + 1)
}
return result
}
但是,当有大量阵列(大约100,000个)进入时,我不知道如何减少时间。我该怎么办?
一些测试用例:
[E,R,E,R,A,R,T,A]->5。因为[2..6]包含所有唯一路径。 (E,R,A,T)
[C,A,A,R,C,A,A,R]-> 3.因为[3..5]包含所有唯一路径。 (C,A,R)
[R,T,A,R,A,R,E,R]->6。因为[1..6]包含所有唯一路径。 (T,A,R,E)
[A,R,R,C,T,E,A,R]->5。因为[2..6]包含所有唯一路径。 (R,C,T,E,A)
答案 0 :(得分:2)
使用“两指针”方法可以有效解决此问题。
使字典结构包含char作为键,并将counter作为值(在最简单的情况下-int数组)
将两个索引L和R设置为0。
向右移动R,以获取相应dict元素的当前char增量计数器。
当dict大小(对于数组-非零元素数)等于unique
时,停止
现在右移L,对于相应的dict元素的当前char减量计数器,当counter变为零时将其删除。当dict大小小于unique
时,请停止。在最后一步,L..R间隔包含所有可能的项目。
继续使用R等等
选择扫描期间的最短间隔。
类似问题here的Python代码
答案 1 :(得分:0)
“所有唯一路径”一词我将解释为“所有可能的值”。
对于具有n
唯一值的长度k
的字符串,这可以在时间O(n log(k))
时使用字典和优先级队列来解决。关键思想是这样:
most_recently_found
,其中包含每个值的最新发现。longest_since
的值自找到以来最长的时间。现在,当您回顾并找到所有值时,将遵循每次迭代逻辑,如下所示:
most_recently_found[current_value] = current_position
oldest = longest_since.top()
if current_value == oldest.value:
while oldest.position() != most_recently_found[oldest.position()]:
longest_since.pop()
longest_since.push({value: top.value, position: most_recently_found[oldest.position()]
oldest = longest_since.top()
if current_position - oldest.position() < best_gap:
best_gap = current_position - oldest.position()
问题在于,对于找到的每个值,您都必须更新字典(O(1)
),可能必须将其从优先级队列(O(k)
)中删除,可能必须添加一些新内容优先级队列(O(k)
),可能需要做一些算术(O(1)
)。因此,O(n log(k))
适用于一切。