[LeetCode] 321. Create Maximum Number 創建最大數


 

Given two arrays of length m and n with digits 0-9 representing two numbers. Create the maximum number of length k <= m + n from digits of the two. The relative order of the digits from the same array must be preserved. Return an array of the k digits.

Note: You should try to optimize your time and space complexity.

Example 1:

Input:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
Output:
[9, 8, 6, 5, 3]

Example 2:

Input:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
Output:
[6, 7, 6, 0, 4]

Example 3:

Input:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
Output:
[9, 8, 9]

Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.

 

這道題給了我們兩個數組,里面數字是無序的,又給我們一個k值為 k <= n1 + n2,然后從兩個數組中共挑出k個數,數字之間的相對順序不變,求能組成的最大的數。這道題的難度是 Hard,博主木有想出解法,參考網上大神們的解法來做的。由於k的大小不定,所以有三種可能:

第一種是當k為0時,兩個數組中都不取數。

第二種是當k不大於其中任意一個數組的長度時,這種情況下,有可能只從一個數組中取數,或者兩個都取一些。

第三種情況是k大於其中任意一個數組的長度,則需要從兩個數組中分別取數,至於每個數組中取幾個,每種情況都要考慮到,然后每次更結果即可。

為了同時能處理這三種情況,這里假設從數組 nums1 中取i個數,那么就需要從 nums2 中取 k-i 個數。那么i的范圍如何確定呢?從情況二中知道,假如k不大於任意一個數組的長度,那么有可能只從其中一個數組中取k個,就是說可以不從 nums1 中取數,所以 i 最小可以取到0。如果是第三種情況,假設k大於 nums2 的長度,就算把 nums2 中所有的數字都取出來,都無法湊個k個,多余的 k-n2 個數字要從 nums1 中來取。所以只要比較 0 和 k-n2 的大小,取較大的為i的起始范圍。那么i最大能到多大呢,還是要看 k 和 n1 的大小,如果 k 小於等於 n1,那么只需要取k個就行了,如果k大於 n1,那么只能在 nums1 中取 n1 個,多余的要到 nums2 中取。

好,現在知道了分別要從兩個數組中取數字的情況,這里希望從 nums1 中取出的i個數字是最大的組合,同理,從 nums2 中取出的 k-i 個也是最大的數字組合。如何才能取出最大的組合呢?比如當前數組長度為n,需要取出k個數字,定義一個變量 drop = n - k,表示需要丟棄的數字的個數,遍歷數組中的數字,進行下列循環,如果此時 drop 為整數,且結果數組長度不為0,結果數組的尾元素小於當前遍歷的元素,則去掉結果數組的尾元素,此時 drop 自減1,重復循環直至上述任意條件不滿足為止,然后把當前元素加入結果數組中,最后返回結果數組中的前k個元素。

現在分別從 nums1 中取出了i個最大組合的數字,從 nums2 中取出了 k-i 個最大組合的數字,最后一步就是需要將兩個取出的數組混合排序成一個數組,小數組中各自的數字之間的相對順序不變。對於兩個數組的混合,要比較了兩個數組的大小(按元素比較),然后從當前比較大的數組里取頭一個元素,然后刪除頭元素到下次再接着比較,直到兩個數組都為空停止。參見代碼如下:

 

class Solution {
public:
    vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
        int n1 = nums1.size(), n2 = nums2.size();
        vector<int> res;
        for (int i = max(0, k - n2); i <= min(k, n1); ++i) {
            res = max(res, mergeVector(maxVector(nums1, i), maxVector(nums2, k - i)));
        }
        return res;
    }
    vector<int> maxVector(vector<int>& nums, int k) {
        int drop = (int)nums.size() - k;
        vector<int> res;
        for (int num : nums) {
            while (drop > 0 && !res.empty() && res.back() < num) {
                res.pop_back();
                --drop;
            }
            res.push_back(num);
        }
        res.resize(k);
        return res;
    }
    vector<int> mergeVector(vector<int> nums1, vector<int> nums2) {
        vector<int> res;
        while (!nums1.empty() || !nums2.empty()) {
            vector<int> &tmp = (nums1 > nums2) ? nums1 : nums2;
            res.push_back(tmp[0]);
            tmp.erase(tmp.begin());
        }
        return res;
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/321

 

類似題目:

Maximum Swap

Remove K Digits

Remove Duplicate Letters

 

參考資料:

https://leetcode.com/problems/create-maximum-number/

https://leetcode.com/problems/create-maximum-number/discuss/77285/Share-my-greedy-solution

https://leetcode.com/problems/create-maximum-number/discuss/77286/Short-Python-Ruby-C%2B%2B

https://leetcode.com/problems/create-maximum-number/discuss/77287/C%2B%2B-16ms-FASTEST-beats-97.

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM