找到具有给定约束的最大和的一对

时间:2018-08-03 09:09:20

标签: arrays algorithm

我最近在一次求职面试中被要求在给定约束下找到两个阵列的最大和。这个问题的措词有所不同,但可以归结为我上面所说的内容。关于元素的不同或数组的排序,一无所知。

示例:

A = [2000, 3000, 4000, 5000]
B = [6000, 5000, 4000, 1000]
Constraint: A[i] + B[j] <= 7000
Expected Result: (A[0], B[1]), (A[1], B[2])

请注意,由于受到限制,这与Find the pair across 2 arrays with kth largest sum是不同的问题。

一种蛮力解决方案是获取2个数组的笛卡尔积,计算每对的和,过滤掉大于7000的对,进行排序,并获取相等的最高值。时间复杂度为O(n 2 )。我们可以做得更好吗?

2 个答案:

答案 0 :(得分:3)

首先,您应该对两个数组进行排序。然后,您可以使用此迭代:

for every number in A:
    perform binary search to find biggest element in B lower than 7000-A

在二进制搜索中找到的数字是与数组A中的当前数字配对的最佳数字。您可以使用这些值中的最大值(对于数组A上的所有迭代)。

二进制搜索以O(logN)时间运行,因此此迭代以O(NlogN)时间运行,而排序也以O(NlogN)时间运行。您可以使用变量更改7000。

答案 1 :(得分:0)

回答我自己的问题,以下是一个可行的解决方案:

public List<Map.Entry> max(int[] a, int[] b, int sum) {
    NavigableMap<Integer, Integer> distMap = new TreeMap<>();
    SortedMap<Integer, List<Map.Entry>> indicesMap = new TreeMap<>();

    for (int i = 0; i < a.length; i++) {
        distMap.put(a[i], i);
    }

    for (int i = 0; i < b.length; i++) {
        int diff = sum - b[i];
        Map.Entry<Integer, Integer> floorEntry = distMap.floorEntry(diff);
        if (Objects.nonNull(floorEntry)) {
            int tmp = b[i] + floorEntry.getKey();
            int j = i;
            indicesMap.merge(
                    tmp,
                    new ArrayList<Map.Entry>() {{
                        add(new AbstractMap.SimpleImmutableEntry<>(floorEntry.getValue(), j));
                    }},
                    (l1, l2) -> {
                        l1.addAll(l2);
                        return l1;
                    }
            );
        }
    }
    return indicesMap.get(indicesMap.lastKey());
}

时间复杂度:O(n)的{​​{1}} + put的{​​{1}},整体O(nlogn)。空间复杂度floorEntry