下面的K-Complementary算法的Big O复杂度是多少?

时间:2017-03-19 21:33:12

标签: algorithm

我正在实现有效的算法,以在给定的A数组中找到K-互补的数字对。 我打算实现O(n)算法。当A数组中的所有数字都不同时,它确定为O(n)。但是我想知道它是否仍然是O(n)如果A数组中的数字可能相等,即在下面提供的测试中,所有元素都相等1.在这个测试中,我们清楚地看到3个元素通过外部循环3次,内部3次。但是,如果一个表有n个元素,其中n属于一组数字,那么所有元素都是相等的是不真实的。 这就是为什么我认为这个内环的复杂性降低到O(1)。

已更新 灵感但不完全满意我的问题的答案我做了一些关于复杂符号定义的深入研究,发现我对上面的计算并不精确。

f(n)= O(g(n))表示存在正常数c和k,因此对于所有n≥k,0≤f(n)≤cg(n)。对于函数f,c和k的值必须是固定的,并且不能取决于n。 根据定义,Big-O给出渐近上界。这意味着如果我们有最坏情况的内部for循环可能遍历n个元素而不是复杂度是O(n ^ 2)。即使从统计上来说这是非常罕见的情况,我们也不能说复杂性小于O(n ^ 2)。然而,有趣的是,如果复杂度O(n ^ 2)真于O(n ^ 3),则定义也是如此。 Big-O

此外,这个算法的Big-Ω复杂度为Ω(n)也是正确的。我们使用大Ω符号表示渐近下界,因为它限制了从足够大的输入大小开始的运行时间的增长。 Big-Ω

据我所知,在将Big-O和Big-Ω收紧到相同值之前,我们无法计算Big-θ

值得注意的是,如果仅检查该数组包含互补对,则下面的算法将是线性的。但是当收集所有互补对时,复杂性增加到O(n ^ 2)。我看了谷歌的采访演示,希望能够获得更多关于主题的线索,但他们将问题简化为“hasComplementaryPair”功能。

关于ComplementaryPair算法的下一步是找到不同的,更快的算法,或者证明它不能更快​​地完成。

更新结束

public class ComplementaryPairs {

    public Set<Pair<Integer, Integer>> process(Integer[] A, Integer k) {
        Set<Pair<Integer, Integer>> pairs = new HashSet<>();
        if (A == null) {
            return pairs;
        }

       /*
        *   1. Build differential map.
        * < k - A[i], i >
        */
        Map<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < A.length; i++) {
            put(map, k - A[i], i);
        }

        /*
         * 2. Collect pairs
         */
        for (int j = 0; j < A.length; j++) {
            if (map.containsKey(A[j])) {

                /*
                 * I've wondered if this loop spoils O(n) complexity,
                 * because in scenario where i.e. we have 10 elements in A and every element is the same,
                 * we have to go through 10 elements in external loop and 10 elements in List in HashMap.
                 *
                 * However, if A table has n elements where n belongs to set of numbers, than situation described above is impossible.
                 * In other words I believe complexity of this inner used to be counted as O(1)
                 *
                 */
                for (Integer iIndex : map.get(A[j])) {
                    pairs.add(new Pair<>(j, iIndex));
                }
            }
        }

        return pairs;
    }

    private void put(Map<Integer, List<Integer>> map, Integer key, Integer value) {
        if (map.containsKey(key)) {
            map.get(key).add(value);
        } else {
            /* This may be improved, so List is not created for one element only */
            List<Integer> list = new LinkedList<>();
            list.add(value);
            map.put(key, list);
        }
    }

}

考虑下面的测试

@Test
public void testWhenArrayContainElementsOfEqualValue() {
    // prepare
    Integer[] A = {1, 1, 1};
    Integer k = 2;

    // execute
    Set<Pair<Integer, Integer>> resultSet = complementaryPairs.process(A, k);

    System.out.println(resultSet);
    // assert
    assertTrue(resultSet.contains(new Pair<>(0, 0)));
    assertTrue(resultSet.contains(new Pair<>(0, 1)));
    assertTrue(resultSet.contains(new Pair<>(0, 2)));
    assertTrue(resultSet.contains(new Pair<>(1, 0)));
    assertTrue(resultSet.contains(new Pair<>(1, 1)));
    assertTrue(resultSet.contains(new Pair<>(1, 2)));
    assertTrue(resultSet.contains(new Pair<>(2, 0)));
    assertTrue(resultSet.contains(new Pair<>(2, 1)));
    assertTrue(resultSet.contains(new Pair<>(2, 2)));

}

1 个答案:

答案 0 :(得分:2)

你读过这个吗? CWD

创建地图是 o(n)运行时但是在你写的时候:

for (int j = 0; j < A.length; j++) {
    if (map.containsKey(A[j])) {
        for (Integer iIndex : map.get(A[j])) {
            pairs.add(new Pair<>(j, iIndex));
        }
    }
}

您的潜在复杂性为 o(n ^ 2)。你应该尽量避免这种情况 然后时间复杂性很明显。

对于代码,仅当存在i k-A [i] == key 时,地图才会包含密钥。

示例:

  

A = [0,0,0,0,0,0],k = 0

由于键0具有数组中的所有元素,并且对于以下示例的所有i,A [i] = 0,所以我满足条件。 所以 n ^ 2 是运行时间。大的复杂性是 o(n ^ 2)

现在出现了一些重复问题。