https://leetcode.com/problems/advantage-shuffle/
Given two arrays
A
and B
of equal size, the advantage of A
with respect to B
is the number of indices i
for which A[i] > B[i]
.
Return any permutation of
A
that maximizes its advantage with respect to B
.
Example 1:
Input: A = [2,7,11,15], B = [1,10,4,11] Output: [2,11,7,15]
Example 2:
Input: A = [12,24,8,32], B = [13,25,32,11] Output: [24,32,8,12]
https://leetcode.com/problems/advantage-shuffle/discuss/149840/C%2B%2BJava-Greedy-Solution-Using-Map
Count elements in
For each element in
Otherwise, we'll take the smallest element.
Then we update the
A
to a map m
.For each element in
B
, find the least bigger element in map m
.Otherwise, we'll take the smallest element.
Then we update the
m
.
Idea is that we need a sorted structure that makes it easy to find a smallest number higher than B[i]. If no such number exists, you use your smallest number from A at that position to maximize our chances to find better positions later.
public int[] advantageCount(int[] A, int[] B) {
TreeMap<Integer, Integer> map = new TreeMap<>();
//Add each number to the map along with count
for (int a : A) map.put(a, map.getOrDefault(a, 0)+1);
int[] ret = new int[A.length];
for (int i = 0; i < B.length; i++) {
//Find the best number to beat B[i]
ret[i] = findBestMatch(B[i], map);
}
return ret;
}
private int findBestMatch(int target, TreeMap<Integer, Integer> map) {
// See if there exists a number higher than the target
Integer res = map.higherKey(target);
// If a number higher than target does not exist, use the smalles available number
if (res == null) res = map.firstKey();
//Update the TreeMap, remove the key if the number has 0 remaining occurences
map.put(res, map.get(res) - 1);
if (map.get(res) == 0) map.remove(res);
return res;
}
https://leetcode.com/problems/advantage-shuffle/discuss/154417/Simple-Java-Solution-with-the-idea-of
运用田忌赛马的思路,如果A中有相应的higher元素,使用最小的higher元素。否则使用A中最小的元素 :)
public int[] advantageCount(int[] A, int[] B) {
// the tree map stores <value, count> pairs of array A
TreeMap<Integer, Integer> map = new TreeMap<>();
for (int num: A) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
// for each value in B, get the A entry with smallest higher key or the smallest key if not exist
int[] res = new int[A.length];
for (int i = 0; i < B.length; i++) {
Map.Entry<Integer, Integer> matchingEntry = map.higherEntry(B[i]);
if (matchingEntry == null) {
matchingEntry = map.firstEntry();
}
res[i] = matchingEntry.getKey();
if (matchingEntry.getValue() == 1) {
map.remove(matchingEntry.getKey());
} else {
map.put(matchingEntry.getKey(), matchingEntry.getValue() - 1);
}
}
return res;
}
If the smallest card
a
in A
beats the smallest card b
in B
, we should pair them. Otherwise, a
is useless for our score, as it can't beat any cards.
Why should we pair
a
and b
if a > b
? Because every card in A
is larger than b
, any card we place in front of b
will score a point. We might as well use the weakest card to pair with b
as it makes the rest of the cards in A
strictly larger, and thus have more potential to score points.
Algorithm
We can use the above intuition to create a greedy approach. The current smallest card to beat in
B
will always be b = sortedB[j]
. For each card a
in sortedA
, we will either have a
beat that card b
(put a
into assigned[b]
), or throw a
out (put a
into remaining
).
Afterwards, we can use our annotations
assigned
and remaining
to reconstruct the answer. Please see the comments for more details.
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;
}
X. PQ
public int[] advantageCount(int[] A, int[] B) {
Arrays.sort(A);
int n=A.length;
int[] res= new int[n];
PriorityQueue<int[]> pq= new PriorityQueue<>((a,b)->b[0]-a[0]);
for (int i=0; i<n; i++) pq.add(new int[]{B[i], i});
int lo=0, hi=n-1;
while(!pq.isEmpty()){
int[] cur= pq.poll();
int idx=cur[1], val=cur[0];
if (A[hi]>val) res[idx]=A[hi--];
else res[idx]=A[lo++];
}
return res;
}
public int[] advantageCount(int[] A, int[] B) {
Arrays.sort(A);
int n=A.length;
int[] res= new int[n];
PriorityQueue<int[]> pq= new PriorityQueue<>(new Comparator<int[]>(){
public int compare(int[] a, int[] b){
return b[0]-a[0];
}
});
for (int i=0; i<n; i++) pq.add(new int[]{B[i], i});
int lo=0, hi=n-1;
while(!pq.isEmpty()){
int[] cur= pq.poll();
int idx=cur[1], val=cur[0];
if (A[hi]>val) res[idx]=A[hi--];
else res[idx]=A[lo++];
}
return res;
}