[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 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索