一、题目描述
二、题目分析
算法
比如
A:{2,8 ,3 ,6}
B:{4,7,9,1}
让A去比较B下标为0的元素4,选取A中比B大的,即{8,6 },让8去比还是6去比呢?
需要拿较小的去比,因为较大的8,可能后面会用到,比如和B的7比。
这就相当于选取A中比B大且刚刚大于的元素,就达到了局部最优,下一次比较同样是寻找刚大于的元素,也是局部最优。
即所有局部最优得到全局最优。就想到了贪心算法,
数据结构
每次选取A中比B大且刚刚大于的元素,达到局部最优,如果先将A由小到大A排序,每次与B比较,只需要遍历A即可,找到比B大且刚刚大于的元素,这个元素就是与B完美配对的,与B中下一个元素比较时就用不到了,删除即可。
A排序后:{2,3,6,8}
B: {4,7,9,1}
开始配对:
- 从头遍历A,配对4——>6,删除A中元素6,
- 从头遍历A,配对7——>8,删除A中元素8
- 从头遍历A,9配对失败
- 从头遍历A,配对1——>2,删除A中元素2
- 那么A中剩余的元素就是3
这样只排序A的话,每次与B中一个元素比较,都要从头遍历A。
如果将B也排序:
A排序后:{2,3,6,8}
B排序后:{1,4,7,9}
开始配对:
- 从头遍历A,配对1——>2
- 从上次配对结束的地方开始遍历,3配对失败,6配对成功,配对4——>6
- 从上次配对结束的地方开始遍历,配对7——>8
- B中剩下9,A中的元素剩下的都比9小
其实A中配对失败元素就是剩下的元素,比B剩下的元素小,直接将A中配对失败元素放入另一个队列或栈中,最后将其出队与B剩下的元素随意配对。
注意:题目要求A随意排列,但B元素下标是固定的,那就需要复制数组B为bsort数组,来辅助与A配对,将B数组每个元素设置为头结点,然后找到该bsort元素在B中的位置,最后将bsort的元素与A配对成功的元素链接在B后面(配对)
最终A中配对元素的顺序就是遍历B中每个链表元素的顺序。
代码
public static int[] advantageCount(int[] A,int[] B){
int[] sortB = B.clone();
Arrays.sort(sortB);
Arrays.sort(A);
Map<Integer, Deque<Integer>> bMap = new HashMap<>();
for (int b : B){
bMap.put(b,new LinkedList<>());
}
Deque<Integer> aq = new LinkedList<>();
int j = 0;
for (int a : A){
if (a > sortB[j]){
bMap.get(sortB[j++]).add(a);
}else {
aq.add(a);
}
}
int[] ans = new int[A.length];
for (int i = 0;i<B.length;i++){
if(bMap.get(B[i]).size()>0){
ans[i] = bMap.get(B[i]).removeLast();
}else {
ans[i] = aq.removeLast();
}
}
return ans;
}