求数组中相等数的最小索引差的算法

时间:2016-05-10 22:43:25

标签: algorithm

有没有人知道如何解决下一个问题:

我们有一个数组,例如让它成为 a = {1,0,-1,-2,-1,0,1,2,3,4,5,1}。

算法应该找到的是相同数字的索引之间的最小差异的大小。 在这个例子中(数组a)1的指数差异是6-0 = 0和11-6 = 5,零指数的差异是5-1 = 4,负数1的差异是4-2 = 2等等。 并且算法应该返回2,因为我们可以看到它是相同数字的索引的最小差异。

有没有办法在时间复杂度上比O(n ^ 2)更好地解决这个问题?

5 个答案:

答案 0 :(得分:3)

其他几个答案提出了可以在O(n * logn)中完成的排序(元素,索引)对。但是,只需 O(n)时间就可以做得更好。无需对数组进行排序,也不需要保留所有(元素,索引)对,因为可以贪婪地找到最小值。

循环遍历数组并将每个元素的最后一个索引存储在散列中。

int smallestDifference(int[] a) {
    Map<Integer, Integer> lastIndex = new HashMap<>();
    int minDiff = Integer.MAX_VALUE;
    for (int i = 0; i < a.length; i++) {
        if (lastIndex.contains(a[i])) {
            minDiff = Math.min(minDiff, i - lastIndex.get(a[i]));
        }
        lastIndex.put(a[i], i);
    }
    return minDiff;
}

从散列中插入/获取是O(1),这样就可以得到整个数组的O(n)。

答案 1 :(得分:2)

制作vector<pair<int, int>>,它会将原始矢量的值与各自的索引存储在一起。对于索引为i的每个值v,将(v,i)添加到向量。

对矢量进行排序(按值然后索引)。

然后浏览有序向量,找到相同值元素之间的最小(或最大,如果需要)距离。

这需要O(n log n)步。

答案 2 :(得分:1)

首先,您可以为序列添加索引(O(N)):

> L = [1, 0, -1, -2, -1, 0, 1, 2, 3, 4, 5, 1].
[1,0,-1,-2,-1,0,1,2,3,4,5,1]
> LI = lists:zip(L, lists:seq(1, length(L))).
[{1,1},
 {0,2},
 {-1,3},
 {-2,4},
 {-1,5},
 {0,6},
 {1,7},
 {2,8},
 {3,9},
 {4,10},
 {5,11},
 {1,12}]

然后你对它进行排序(O(N log N)):

> LS = lists:sort(LI).
[{-2,4},
 {-1,3},
 {-1,5},
 {0,2},
 {0,6},
 {1,1},
 {1,7},
 {1,12},
 {2,8},
 {3,9},
 {4,10},
 {5,11}]

然后你找到所有相同值的距离(O(N)):

> LD = (fun F([{X, P1}|[{X,P2}|_]=T]) -> [{P2-P1, X, {P1, P2}} | F(T)]; F([_|T]) -> F(T); F([]) -> [] end)(LS).
[{2,-1,{3,5}},{4,0,{2,6}},{6,1,{1,7}},{5,1,{7,12}}]

然后你找到最小距离(O(N)):

> lists:min(LD).
{2,-1,{3,5}}

这意味着位置3和5之间的值-1的最小距离2,结果复杂度为O(N log N)。 (示例代码在Erlang中。)

答案 3 :(得分:0)

以下算法适用于 1) Make a map of <int,vector<int> > . 2) Let the number be the key and the indexes be the vector. 3) sort the vector for all the keys. 4) Now find the minimum difference for all the difference between indices.

1 2 3 2 1 3

例如:对于数组1 -> [0,4] 2 ->[1,3] 3 -> [2,5]

GregorianCalendar calDate = new GregorianCalendar();

在这里我们可以看到3-1 = 2将给出索引的最小差异。

答案 4 :(得分:0)

这是用Go编程语言编写的。

func smallestIndexDifference(numbers []int) (mindiff int, exists bool) {
  var prev map[int]int // The previous index where this number was found
  for i, number := range numbers {
    prevIndex, found := prev[number]
    if found {
      diff := i - prevDiff
      if !exists || diff < mindiff {
        exists, mindiff = true, diff
      }
    }
    prev[number] = i
  }
  return
}

这是完全未经测试的,但如果它完全有效,它可以在O(n log n)中工作。