LeetCode -- Create Maximum Number

Question:

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]

 

Analysis:

给出长度分别为m和n,由数字0-9构成的两个数组。给定一个k <= m + n,创建一个长度为k的最大数字,其中的数字由给出的两个数组决定,且同一个数组中数字的先后顺序要保持。

思路:

解决这个题目主要要解决两个子问题:

1)每个数组中要拿出几个数字?

2)拿出的这几个数字是什么?

3)如何将两个基本有序的数组合并成一个?

这样,分别从两个数组中取出一个子数组后,将两个子数组合并就可以了。

所以我们首先解决第一个问题:

  • 每个数组中要拿出几个数字?方法只能是分情况讨论,然后遍历所有的组合可能;

然后,解决第二个问题:

  • 拿出的这几个数字是什么?用一个栈保存当前结果。所有对于某个元素只有两种可能:一种是入栈,一种是更新。

  • 当 栈不空 && 后面还有足够的数字可以形成长度为k的数组 && 栈顶元素<当前元素,则应该用当前元素替换栈顶元素;

  • 其他情况下入栈就可以了。

最后,合并两个子数组。

  • 类似两个链表merge的操作,每次选择两者中最大的一个即可。

 

代码如下:

public class Solution {
    public int[] maxNumber(int[] nums1, int[] nums2, int k) {
        if(k == 0) return new int[0];
        int m = nums1.length, n = nums2.length;
        if(m + n < k) return null;
        if(m + n == k) {
            int[] res = makeMerge(nums1, nums2, k);
            return res;
        }
        else { //m+n > k
            int max = m >= k ? k : m; //max means the max number of stack1
            int min = n >= k ? 0 : k-n;
            int[] res = new int[k];
            for(int i=0; i<k; i++)
                res[i] = -0x7ffffffe;
            for(int i=min; i<=max; i++) {
                int[] temp = makeMerge(getMax(nums1, i), getMax(nums2, k-i), k);
                res = isGreater(res, 0, temp, 0) ? res : temp;
            }
            return res;
        }
    }

    private int[] makeMerge(int[] nums1, int[] nums2, int k) {
        int[] res = new int[k];
        if(k == 0) return res;
        int i = 0, j = 0;
        for(int t=0; t<k; t++ ) {
            res[t] = isGreater(nums1, i, nums2, j) ? nums1[i++] : nums2[j++];
        }
        return res;
    }
    private boolean isGreater(int[] nums1, int i, int[] nums2, int j) {
        // TODO Auto-generated method stub
        for(; i<nums1.length && j<nums2.length; i++, j++) {
            if(nums1[i] > nums2[j]) return true;
            if(nums1[i] < nums2[j]) return false;
        }
        return i != nums1.length;
    }

    private int[] getMax(int[] nums, int k) {
        if(k == 0) return new int[0];
        int[] res = new int[k];
        int i = 0;
        for(int j=0; j<nums.length; j++) {
            while(nums.length - j + i > k && i > 0 && res[i-1] < nums[j])
                i--;
            if(i < k)
                res[i++] = nums[j];
        }
        return res;
    }
    
}

 

posted @ 2016-04-14 13:10  江湖小妞  阅读(416)  评论(0编辑  收藏  举报