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. You should try to optimize your time and space complexity.
Given nums1 = [3, 4, 6, 5]
, nums2 = [9, 1, 2, 5, 8, 3]
, k = 5
return [9, 8, 6, 5, 3]
Given nums1 = [6, 7]
, nums2 = [6, 0, 4]
, k = 5
return [6, 7, 6, 0, 4]
Given nums1 = [3, 9]
, nums2 = [8, 9]
, k = 3
return [9, 8, 9]
分析:http://bookshadow.com/weblog/2015/12/24/leetcode-create-maximum-number/
问题可以转化为这样的两个子问题:
1. 从数组nums中挑选出t个数,在保持元素相对顺序不变的情况下,使得选出的子数组最大化。 2. 在保持元素相对顺序不变的前提下,将数组nums1与数组nums2合并,使合并后的数组最大化。
枚举nums1子数组与nums2子数组的长度len1, len2,在满足长度之和len1+len2等于k的前提下,分别求解最大子数组,并进行合并。
然后从合并得到的子数组中取最大数组即为所求。
1 public class Solution { 2 public int[] maxNumber(int[] nums1, int[] nums2, int k) { 3 int n = nums1.length, m = nums2.length; 4 int[] ans = new int[k]; 5 for (int i = Math.max(0, k - m); i <= Math.min(n, k); ++i) { 6 int[] candidate = merge(maxArray(nums1, i), maxArray(nums2, k - i), k); 7 if (isGreater(candidate, 0, ans, 0)) ans = candidate; 8 } 9 return ans; 10 } 11 12 private int[] merge(int[] nums1, int[] nums2, int k) { 13 int[] ans = new int[k]; 14 for (int i = 0, j = 0, r = 0; r < k; ++r) { 15 ans[r] = isGreater(nums1, i, nums2, j) ? nums1[i++] : nums2[j++]; 16 } 17 return ans; 18 } 19 20 public boolean isGreater(int[] nums1, int i, int[] nums2, int j) { 21 while (i < nums1.length && j < nums2.length && nums1[i] == nums2[j]) { 22 i++; 23 j++; 24 } 25 return j == nums2.length || (i < nums1.length && nums1[i] > nums2[j]); 26 } 27 28 public int[] maxArray(int[] arr, int k) { 29 int p = -1; 30 int[] nums = new int[k]; 31 if (k == 0) return nums; 32 33 for (int i = 0; i < arr.length; i++) { 34 while (p >= 0 && nums[p] < arr[i] && (arr.length - i + p + 1) > k) { 35 p--; 36 } 37 if (p < nums.length - 1) { 38 p++; 39 nums[p] = arr[i]; 40 } 41 } 42 return nums; 43 } 44 }