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.

Example

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 }