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]
.html
Return any permutation of A
that maximizes its advantage with respect to B
.git
Example 1:github
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]
Note:数组
1 <= A.length = B.length <= 10000
0 <= A[i] <= 10^9
0 <= B[i] <= 10^9
这道题给了咱们两个数组A和B,让对A进行重排序,使得每一个对应对位置上A中的数字尽量的大于B。这不就是大名鼎鼎的田忌赛马么,但想出高招并非田忌,而是孙膑,就是孙子兵法的做者,但这 credit 好像都给了田忌,让人误觉得是田忌的智慧,不由想起了高富帅重金买科研成果的冠名权的故事。孙子原话是,“今以君之下驷与彼上驷,取君上驷与彼中驷,取君中驷与彼下驷”。就是本身的下马跟人上马比,稳输不用管,上马跟其中马跑,稳赢,中马跟其下马跑,仍是稳赢。那我还全马跟其半马跑,能赢否?不过说的,今天博主所在的城市还真有马拉松比赛,并且博主还报了半马,可是因为身不禁己的缘由没法去跑,实在是惋惜,没事,来日方长,老是有机会的。扯了这么久的犊子,赶忙拉回来作题吧。其实这道题的思路还真是田忌赛马的智慧同样,既然要想办法大过B中的数,那么对于B中的每一个数(能够看做每匹马),先在A中找恰好大于该数的数字(这就是为啥中马跟其下马比,而不是上马跟其下马比),用太大的数字就浪费了,而若是A中没有比之大的数字,就用A中最小的数字(用下马跟其上马比,不过略有不一样的是此时咱们没有上马)。就用这种贪婪算法的思路就能够成功解题了,为了方便起见,就是用一个 MultiSet 来作,至关于一个容许重复的 TreeSet,既容许重复又自带排序功能,岂不美哉!那么遍历B中每一个数字,在A进行二分搜索第一个大于的数字,这里使用了 STL 自带的 upper_bound 来作,固然想本身写二分也没问题。而后看,若不存在,则将A中最小的数字加到结果 res 中,不然就将第一个大于的数字加入结果 res 中,参见代码以下:指针
解法一:code
class Solution { public: vector<int> advantageCount(vector<int>& A, vector<int>& B) { vector<int> res; multiset<int> st(A.begin(), A.end()); for (int i = 0; i < B.size(); ++i) { auto it = (*st.rbegin() <= B[i]) ? st.begin() : st.upper_bound(B[i]); res.push_back(*it); st.erase(it); } return res; } };
当两个数组都是有序的时候,咱们就能快速的直到各自的最大值与最小值,问题就变得容易不少了。好比能够先从B的最大值开始,这是就看A的最大值可否大过B,能的话,就移动到对应位置,不能的话就用最小值,而后再看B的次大值,这样双指针就能够解决问题。因此能够先给A按从小到大的顺序,对于B的话,不能直接排序,由于这样的话原来的顺序就彻底丢失了,因此将B中每一个数字和其原始坐标位置组成一个 pair 对儿,加入到一个最大堆中,这样B中的最大值就会最早被取出来,再进行上述的操做,这时候就能够发现保存的原始坐标就发挥用处了,根据其坐标就能够直接更新结果 res 中对应的位置了,参见代码以下:htm
解法二:blog
class Solution { public: vector<int> advantageCount(vector<int>& A, vector<int>& B) { int n = A.size(), left = 0, right = n - 1; vector<int> res(n); sort(A.begin(), A.end()); priority_queue<pair<int, int>> q; for (int i = 0; i < n; ++i) q.push({B[i], i}); while (!q.empty()) { int val = q.top().first, idx = q.top().second; q.pop(); if (A[right] > val) res[idx] = A[right--]; else res[idx] = A[left++]; } return res; } };
Github 同步地址:排序
https://github.com/grandyang/leetcode/issues/870
参考资料:
https://leetcode.com/problems/advantage-shuffle/
https://leetcode.com/problems/advantage-shuffle/discuss/149831/C%2B%2B-6-lines-greedy-O(n-log-n)
https://leetcode.com/problems/advantage-shuffle/discuss/149822/JAVA-Greedy-6-lines-with-Explanation