1. 程式人生 > >Leetcode 321.拼接最大數

Leetcode 321.拼接最大數

拼接最大數

給定長度分別為 m 和 n 的兩個陣列,其元素由 0-9 構成,表示兩個自然數各位上的數字。現在從這兩個陣列中選出 k (k <= m + n) 個數字拼接成一個新的數,要求從同一個陣列中取出的數字保持其在原陣列中的相對順序。

求滿足該條件的最大數。結果返回一個表示該最大數的長度為 k 的陣列。

說明: 請儘可能地優化你演算法的時間和空間複雜度。

示例 1:

輸入:

nums1 = [3, 4, 6, 5]

nums2 = [9, 1, 2, 5, 8, 3]

k = 5

輸出:

[9, 8, 6, 5, 3]

示例 2:

輸入:

nums1 = [6, 7]

nums2 = [6, 0, 4]

k = 5

輸出:

[6, 7, 6, 0, 4]

示例 3:

輸入:

nums1 = [3, 9]

nums2 = [8, 9]

k = 3

輸出:

[9, 8, 9]

 

首先採用分治法的思路,我們知道這K個數字中,必然有i個數組來自nums1,而剩下的k-i個數字必然來自nums2。那麼問題變成從nums1中獲取i個數,這i個數構成的數字最大,且這i個數字的相對位置不變。再從nums2中獲取k-i個數,這k-i個數構成的數字最大,且這k-i個數字的相對位置不變。

那麼我們如何將這兩個結果合併起來獲得我們最終的結果呢?這裡很像歸併演算法的merge過程,我們從兩個陣列的開頭獲取最大的值加進來唄。那如果出現相同的值怎麼辦?那麼繼續比較,直到遇到第一個不相同的數字,然後選擇數字較大的那個陣列。

 

 1 public class Solution {
 2     private int[] max(int[] nums, int k) {
 3         int[] max = new int[k];
 4         for(int i=0, j=0; i<nums.length; i++) {
 5             while
(j>0 && k-j<nums.length-i && max[j-1]<nums[i]) j--; 6 if (j<k) max[j++] = nums[i]; 7 } 8 return max; 9 } 10 11 private int[] merge(int[] nums1, int[] nums2) { 12 int[] merged = new int[nums1.length+nums2.length]; 13 for(int i=0, j=0, m=0; m<merged.length; m++) { 14 merged[m] = greater(nums1, i, nums2, j) ? nums1[i++] : nums2[j++]; 15 } 16 return merged; 17 } 18 19 private boolean greater(int[] nums1, int i, int[] nums2, int j) { 20 while (i<nums1.length && j<nums2.length && nums1[i]==nums2[j]) { 21 i++; 22 j++; 23 } 24 return j==nums2.length || (i<nums1.length && nums1[i]>nums2[j]); 25 } 26 27 public int[] maxNumber(int[] nums1, int[] nums2, int k) { 28 int[] max = null; 29 for(int i=Math.max(k-nums2.length, 0); i<=Math.min(nums1.length, k); i++) { 30 int[] merged = merge(max(nums1, i), max(nums2, k-i)); 31 if (max == null || greater(merged, 0, max, 0)) max = merged; 32 } 33 return max; 34 } 35 }