标签:
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]
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
The solution is inspired by @dietpepsi and @chellya based on the following posts:
[1]: https://discuss.leetcode.com/topic/32272/share-my-greedy-solution
[2]: https://discuss.leetcode.com/topic/36805/c-16ms-fastest-beats-97
I used optimization introduced in [2] and the merge method introduced in [1].
To summarize:
NOTE:
DP solution is like this:
dp[i][j][k]: the max number with length k, using nums1[0..i] and nums2[0...j].
dp[i][j][k] = max{ dp[i-1][j][k], dp[i][j-1][k], (nums1[i]+dp[i-1][j][k-1]), (nums2[j]+dp[i][j-1][k-1])}.
While the greedy solution is really hard to figure out in a short time, the DP solution is much easier to derive.
Solution:
public class Solution { public int[] maxNumber(int[] nums1, int[] nums2, int k) { if (k==0) return new int[k]; if (nums1.length==0){ return getMaxNumberFromNums(nums2,k); } if (nums2.length==0){ return getMaxNumberFromNums(nums1,k); } // Generates the max number of nums2 with the max possible length. int[] maxNum2 = getMaxNumberFromNums(nums2,Math.min(nums2.length,k)); // Generates the max number of nums2 of each possible length. Deque<int[]> maxNums2 = getMaxNumsForAllLenth(maxNum2,Math.max(k-nums1.length, 0)); int[] maxNum1 = getMaxNumberFromNums(nums1,Math.min(nums1.length,k)); int[] res = new int[k]; for (int len1 = Math.min(nums1.length,k);len1>=Math.max(k-nums2.length,0);len1--){ if (len1 < Math.min(nums1.length,k)){ maxNum1 = getMaxNumWithOneLessLen(maxNum1); } maxNum2 = maxNums2.pollFirst(); res = getNewMaxNumber(res,maxNum1,maxNum2); } return res; } // Get max number with length of maxNumLen from nums. public int[] getMaxNumberFromNums(int[] nums, int maxNumLen){ int[] maxNum = new int[maxNumLen]; int len = nums.length; int end = 0; for (int i=0;i<len;i++){ while (end >= 1 && maxNum[end-1] < nums[i] && len - i > maxNumLen - end){ end--; } if (end < maxNumLen) maxNum[end++] = nums[i]; } return maxNum; } // Get max numbers with length of maxNum.length, maxNum.length-1, ..., minLen, based on maxNum. public Deque<int[]> getMaxNumsForAllLenth(int[] maxNum, int minLen){ Deque<int[]> maxNums = new LinkedList<int[]>(); maxNums.add(maxNum); while (maxNum.length>minLen){ int[] nextNum = getMaxNumWithOneLessLen(maxNum); maxNums.addFirst(nextNum); maxNum = nextNum; } return maxNums; } // Get the max number with length of maxNum.length-1 from maxNum. public int[] getMaxNumWithOneLessLen(int[] maxNum){ int len = maxNum.length, end = 0; int[] nextNum = new int[len-1]; boolean deleted = false; for (int i=0;i<len;i++){ if (end >= len-1) break; if ((i==len-1 || maxNum[i] >= maxNum[i+1]) || deleted){ nextNum[end++] = maxNum[i]; } else { deleted = true; } } return nextNum; } // Merge part1 and part2 into a new max number, substitute the old one if the new one is larger. public int[] getNewMaxNumber(int[] maxNum, int[] part1, int[] part2){ int[] newNum = new int[maxNum.length]; int p1 = 0, p2 = 0, index = 0; boolean newNumLarger = false; while (p1 < part1.length || p2 < part2.length){ newNum[index] = (greater(part1,p1,part2,p2)) ? part1[p1++] : part2[p2++]; // Early termination, if we find new number is less than the existing one. if (maxNum[index] > newNum[index] && !newNumLarger){ return maxNum; } else if (maxNum[index] < newNum[index]){ newNumLarger = true; } index++; } return newNum; } // This is function is important. When merging two parts into the max number, we need address the case part1[p1] == part2[p2]. public boolean greater(int[] part1, int p1, int[] part2, int p2){ while (p1<part1.length && p2<part2.length && part1[p1]==part2[p2]){ p1++; p2++; } return p2==part2.length || (p1 < part1.length && part1[p1] > part2[p2]); } }
LeetCode-Create Maximum Number
标签:
原文地址:http://www.cnblogs.com/lishiblog/p/5838597.html