第十九題:優勢洗牌
阿新 • • 發佈:2018-12-30
問題描述
給定兩個大小相等的陣列 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; } }