利用O(nlogn)时间O(1)空间有效地计算数组中的等值对的数量

时间:2014-11-06 14:06:55

标签: java algorithm duplicates

给定一组int值:

{4, 2, 6, 5, 4, 4, 5}

合格对的索引是

{0, 4}
{0, 5}
{4, 5}
{3, 6}

第二个索引应该大于第一个索引。所以正确的结果是4.

请注意,最坏​​情况下的时间复杂度为O(nlogn),最坏情况下的空间复杂度为O(1)。

朴素解决方案:两个循环,但是O(n ^ 2)。

我的解决方案:对数组进行快速排序,然后变为{2, 4, 4, 4, 5, 5, 6},如果它出现多次,则计算元素数量:例如:4的数量是3,count + = 3 * 2/2 = 3, 5的数量是2,计数+ = 2 * 1/2 = 1。

我的解决方案的问题:最坏情况可能有O(n ^ 2),但它需要O(1)空间,所以我没有选择合并排序。

有人可以提供一个好的解决方案吗?谢谢。

3 个答案:

答案 0 :(得分:1)

我能想到的最简单的代码是使用Set:

int duplicateCount = 0;
Set<Integer> set = new HashSet<>();
for (int n : numbers)
    if (!set.add(n))
        duplicateCount++;

或java 8:

Set<Integer> set = new HashSet<>();
int dups = Arrays.stream(numbers).filter(n -> !set.add(n)).count();

如果添加更改了集合(即它是一个新数字),Set的add()方法返回true,否则返回false(即它是重复的)。

HashSet具有出色的性能 - O(1) - 并且算法是O(n)性能和(取决于分布)&lt; O(n)空间。


如果你真的需要O(1)空间,你可以使用Arrays.sort(int\[\])对数组进行排序(在Java 7中的实现使用双枢轴快速进程,这是一个就地 - 即O(1) - 算法)然后添加此代码:

Arrays.sort(numbers);
int dups = 0;
for (int i = 1; i < numbers.length; i++)
    if (numbers[i] = numbers[i - 1])
        dups++;

Arrays.sort()非常有效O(nlogn)并且没有额外的空间使用O(1)。

答案 1 :(得分:0)

应该是

        private static int GetCount(int count)
    {
        if(count == 0)
        {
            return 0;
        }
        return (count + 1) * count / 2;
    }

    public static int solution1(int[] a)
    {
        Array.Sort(a);
        int count = 0;
        int currentCount = 0;
        for (int i = 1; i < a.Length; i++)
        {
            if (a[i - 1] == a[i])
            {
                currentCount++;
            }
            else
            {
                count += GetCount(currentCount);
                currentCount = 0;
            }
        }
        count += GetCount(currentCount);
        return count;
    }

答案 2 :(得分:0)

public static int solution(int[] A) {
    Map<Integer, Integer> map = new HashMap();
    // make count of each element
    for (int element : A) {
        if (map.containsKey(element)) {
            map.put(element, map.get(element) + 1);
        } else {
            map.put(element, 1);
        }
    }
    // count number of pair of pairs
    return map.entrySet().stream()
            .mapToInt(IdenticalPair::countPair).sum();
}

private static int countPair(Map.Entry<Integer, Integer> entry) {
    /**
     * ((elementCount - 1)) * elementCount / 2;
     * (1-1)*1/2 = 0
     * (2-1)*2/2 = 1
     * (3-1)*3/2 = 3
     * (4-1)*4/2 = 6
     * and so on.....
     */
    return ((entry.getValue() - 1)) * entry.getValue() / 2;
}