1. 程式人生 > >第十九題:優勢洗牌

第十九題:優勢洗牌

問題描述

給定兩個大小相等的陣列 A 和 B,A 相對於 B 的優勢可以用滿足 A[i] > B[i] 的索引 i 的數目來描述。

返回 A 的任意排列,使其相對於 B 的優勢最大化。

示例 1:

輸入:A = [2,7,11,15], B = [1,10,4,11]
輸出:[2,11,7,15]
示例 2:

輸入:A = [12,24,8,32], B = [13,25,32,11]
輸出:[24,32,8,12]

提示:

1 <= A.length = B.length <= 10000
0 <= A[i] <= 10^9
0 <= B[i] <= 10^9

解決方式

貪心
思路

如果 A 中最小的牌 a 能擊敗 B 中最小的牌 b,那麼我們應當將它們配對。否則, a 將無益於我們的比分,因為它無法擊敗任何牌。

我們為什麼要在 a > b 時將 a 和 b 配對呢?這是因為此時在 A 中的每張牌都比 b 要大,所以不管我們在 b 前面放置哪張牌都可以得分。我們可以用手中最弱的牌來與 b 配對,這樣會使 A 中剩餘的牌嚴格地變大,因此會有更多得分點。

演算法

我們可以根據上面的思路來創造一種貪心演算法。目前在 B 中要被擊敗的最小的牌將始終是 b = sortedB[j]。對於在 sortedA 中的每張卡 a,要麼 a 能夠擊敗牌 b(將 a 放入 assigned[b]),要麼把 a 扔掉(將 a 放入 remaining)。

之後,我們可以使用此前標註的 assigned 和 remaining 來重構答案。詳細情況請查閱註釋。

Java語言:

class Solution {
    public int[] advantageCount(int[] A, int[] B) {
        int[] sortedA = A.clone();
        Arrays.sort(sortedA);
        int[] sortedB = B.clone();
        Arrays.sort(sortedB);

        // assigned[b] = list of a that are assigned to beat b
        Map<Integer, Deque<Integer>> assigned = new HashMap();
        for (int b: B) assigned.put(b, new LinkedList());

        // remaining = list of a that are not assigned to any b
        Deque<Integer> remaining = new LinkedList();

        // populate (assigned, remaining) appropriately
        // sortedB[j] is always the smallest unassigned element in B
        int j = 0;
        for (int a: sortedA) {
            if (a > sortedB[j]) {
                assigned.get(sortedB[j++]).add(a);
            } else {
                remaining.add(a);
            }
        }

        // Reconstruct the answer from annotations (assigned, remaining)
        int[] ans = new int[B.length];
        for (int i = 0; i < B.length; ++i) {
            // if there is some a assigned to b...
            if (assigned.get(B[i]).size() > 0)
                ans[i] = assigned.get(B[i]).pop();
            else
                ans[i] = remaining.pop();
        }
        return ans;
    }
}

執行結果展示

在這裡插入圖片描述