LeetCode321 Create Maximum Number

we are given two arrays which have length m and n with digits 0-9 representing two numbers. and we have to create a K digits number that coming from those two arrays. and the relative order should be preserved in the new K digits number.
now, what we want is to make this K digits number as large as possible.

and we can be guaranteed that K<= m+n

well, this problem is actually quite like LC402. Remove K Digits, which in that problem, we have to remove K digits and left remaining as smaller as possible.
now this time, we need to find the maximum subsequence combination of two given arrays.

this problem can actually be solved in a smaller scale.

  1. create the maximum number of one array
  2. create the maximum number of two arrays using all of their digits

so that makes the following code:
it may seems complicated, but each function is easy to understand and we just need to use all these in our overall function to solve this problem.

public int[] maxNumber(int[] nums1, int[] nums2, int k) {
    int n = nums1.length;
    int m = nums2.length;
    int[] ans = new int[k];
    for (int i = Math.max(0, k - m); i <= k && i <= n; ++i) { //i as the split mid point
        int[] candidate = merge(maxArray(nums1, i), maxArray(nums2, k - i), k); //find the maxArray if we can only use i elements in nums1, and we find the maxArray if we can only use k-i elements in nums2. and we merge those two. and we use this as the candidate.
        if (greater(candidate, 0, ans, 0)) ans = candidate; //only when we need update the overall maximum will we update the final answer, why do we have to write a independent function to judge which one is greater? because in the merge() function, we still need that
    }
    return ans;
}
private int[] merge(int[] nums1, int[] nums2, int k) { //why do we have to use k as a parameter? because we need to use this to initialized the length the array we are gonna to output as result
    int[] ans = new int[k];
    for (int i = 0, j = 0, r = 0; r < k; ++r)
        ans[r] = greater(nums1, i, nums2, j) ? nums1[i++] : nums2[j++];
    return ans;
}
public boolean greater(int[] nums1, int i, int[] nums2, int j) {  //check where nums1(startiing from index i) is larger or nums2(starting from index j) is larger
    while (i < nums1.length && j < nums2.length && nums1[i] == nums2[j]) {
        i++;
        j++;
    }
    return j == nums2.length || (i < nums1.length && nums1[i] > nums2[j]);
}
private int[] maxArray(int[] nums, int len) {
        Stack<Integer> stack = new Stack<Integer>();
        for (int i = 0; i < nums.length; i++) {
            while (stack.size() + nums.length - i > len && !stack.empty() && stack.peek() < nums[i]) { //decreasing stack
                stack.pop();
            }
            if (stack.size() < len) { //only when current size is less than len will we push current number to stack, which means if we have more than len number of elements in stack, then we have already got the first len length maximum sequence
                stack.push(nums[i]);
            }
        }
        int[] result = new int[len];
        for (int i = len - 1; i >= 0; i--) {
          result[i] = stack.pop(); 
        }
        return result;
    }
posted @ 2020-05-31 12:09  EvanMeetTheWorld  阅读(11)  评论(0)    收藏  举报