[LeetCode] 870. 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].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. 1 <= A.length = B.length <= 10000
  2. 0 <= A[i] <= 10^9
  3. 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



LeetCode All in One 题目讲解汇总(持续更新中...)

相关文章
相关标签/搜索