Problem:
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 1:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
return [9, 8, 6, 5, 3]
Example 2:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
return [6, 7, 6, 0, 4]
Example 3:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
return [9, 8, 9]
题目大意:给你两个数字数组和k,返回从两个数组中选取k个数字能够组成的最大值。
Idea: Greedy + DP
Solution:
Time complexity: O(k * (n1+n2)^2)
Space complexity: O(n1+n2)
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
// Author: Huahua // Runtime: 26 ms class Solution { public: vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) { vector<int> ans; const int n1 = nums1.size(); const int n2 = nums2.size(); for (int i = max(0, k - n2); i <= min(k, n1); ++i) ans = max(ans, maxNumber(maxNumber(nums1, i), maxNumber(nums2, k - i))); return ans; } private: vector<int> maxNumber(const vector<int>& nums, int k) { vector<int> ans(k); int j = 0; for (int i = 0; i < nums.size(); ++i) { while (j > 0 && nums[i] > ans[j - 1] && nums.size() - i > k - j) --j; if (j < k) ans[j++] = nums[i]; } return ans; } vector<int> maxNumber(const vector<int>& nums1, const vector<int>& nums2) { vector<int> ans(nums1.size() + nums2.size()); auto s1 = nums1.cbegin(); auto e1 = nums1.cend(); auto s2 = nums2.cbegin(); auto e2 = nums2.cend(); int index = 0; while (s1 != e1 || s2 != e2) ans[index++] = lexicographical_compare(s1, e1, s2, e2) ? *s2++ : *s1++; return ans; } }; |
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
// Author: Huahua // Runtime: 18 ms class Solution { public int[] maxNumber(int[] nums1, int[] nums2, int k) { int[] best = new int[0]; for (int i = Math.max(0, k - nums2.length); i <= Math.min(k, nums1.length); ++i) best = max(best, 0, maxNumber(maxNumber(nums1, i), maxNumber(nums2, k - i)), 0); return best; } private int[] maxNumber(int[] nums, int k) { int[] ans = new int[k]; int j = 0; for (int i = 0; i < nums.length; ++i) { while (j > 0 && nums[i] > ans[j - 1] && nums.length - i > k - j) --j; if (j < k) ans[j++] = nums[i]; } return ans; } private int[] maxNumber(int[] nums1, int[] nums2) { int[] ans = new int[nums1.length + nums2.length]; int s1 = 0; int s2 = 0; int index = 0; while (s1 != nums1.length || s2 != nums2.length) ans[index++] = max(nums1, s1, nums2, s2) == nums1 ? nums1[s1++] : nums2[s2++]; return ans; } private int[] max(int[] nums1, int s1, int[] nums2, int s2) { for (int i = s1; i < nums1.length; ++i) { int j = s2 + i - s1; if (j >= nums2.length) return nums1; if (nums1[i] < nums2[j]) return nums2; if (nums1[i] > nums2[j]) return nums1; } return nums2; } } |