给定一个int数组,每个int在该数组中正好显示为TWICE 阵列。找到并返回int,使得这对int具有最大值 这个数组中彼此之间的距离。
e.g。 [2, 1, 1, 3, 2, 3]
2: d = 5-1 = 4;
1: d = 3-2 = 1;
3: d = 6-4 = 2;
return 2
我的想法:
使用hashmap,key是a[i]
,value是索引。扫描a[]
,将每个数字放入哈希值。如果数字被命中两次,请使用其索引减去旧数字索引并使用结果更新哈希中的元素值。
之后,扫描哈希并返回具有最大元素(距离)的密钥。 在时间和空间上都是O(n)。
如何在O(n)时间和O(1)空间中进行操作?
答案 0 :(得分:2)
您希望拥有最大距离,因此我假设您搜索的数字更可能位于开头和结尾。这就是为什么我会在同一时间从开始和结束循环遍历数组的原因。
[2, 1, 1, 3, 2, 3]
Check if 2 == 3?
Store a map of numbers and position: [2 => 1, 3 => 6]
Check if 1 or 2 is in [2 => 1, 3 => 6] ?
我知道,这甚至不是伪代码,也不是完整的,只是为了表达这个想法。
答案 1 :(得分:0)
将iLeft索引设置为第一个元素,将iRight索引设置为第二个元素。 增加iRight索引,直到找到左项的副本或满足数组的末尾。在第一种情况下 - 记住距离。
增量iLeft。从新的iRight开始搜索。 iRight的起始值永远不会减少。 德尔福代码:
iLeft := 0;
iRight := 1;
while iRight < Len do begin //Len = array size
while (iRight < Len) and (A[iRight] <> A[iLeft]) do
Inc(iRight); //iRight++
if iRight < Len then begin
BestNumber := A[iLeft];
MaxDistance := iRight - iLeft;
end;
Inc(iLeft); //iLeft++
iRight := iLeft + MaxDistance;
end;
答案 2 :(得分:0)
该算法为O(1)空间(有一些作弊),O(n)时间(平均值),需要源数组为非const并在最后销毁它。它还限制了数组中的可能值(应为算法保留每个值的三位)。
答案的一半已经存在。使用hashmap。如果一个数字被命中两次,使用索引差异,更新最好的结果,并从hashmap中删除此数字以释放空间。要使其成为O(1)空间,只需重用源数组即可。将数组原地转换为hashmap。
在将数组元素转换为hashmap单元格之前,请记住它的值和位置。在此之后它可能被安全地覆盖。然后使用此值计算hashmap中的新位置并覆盖它。元素以这种方式混洗,直到找到空单元格。要继续,请选择尚未重新排序的任何元素。当一切都被重新排序时,每个int对肯定会被击中两次,这里我们有一个空的hashmap和一个更新的最佳结果值。
在将数组元素转换为hashmap单元格时使用一个保留位。一开始它被清除了。将值重新排序到hashmap单元格时,将设置此位。如果没有为覆盖的元素设置该位,则仅接下来处理该元素。如果为要覆盖的元素设置此位,则此处存在冲突,请选择第一个未使用的元素(未设置此位)并覆盖它。
另外2个保留位用于链接冲突值。它们编码链开始/结束/继续的位置。 (有可能优化该算法,因此只需要2个保留位...)
散列映射单元应包含这3个保留位,原始值索引以及用于唯一标识此元素的一些信息。为了实现这一点,哈希函数应该是可逆的,以便在给定其在表中的位置时可以恢复部分值。在最简单的情况下,散列函数只是ceil(log(n))
最低有效位。表中的值由3个字段组成:
3
保留位32 - 3 - (ceil(log(n)))
来自原始值的高阶位ceil(log(n))
位时间复杂度仅为平均O(n);最坏情况复杂度为O(n ^ 2)。
此算法的其他变体是按顺序将数组转换为hashmap:在每个步骤m
上,将2^m
数组的第一个元素转换为hashmap。当m
为低时,某些恒定大小的数组可以与散列映射交错以提高性能。当m
为高时,应该有足够的int对,它们已经处理完毕,不再需要空格了。
答案 3 :(得分:0)
在O(n)时间和O(1)空间中无法做到这一点。