Leetcode 321. Create Maximum Number

问题描述:

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.

问题分析:
问题要求从两个数组中选择k个数字,使得新组成数字是最大的,并且保证选择的数字不改变在原来数组中的相对顺序。
问题可以转化为两个子问题:

1、从数组nums中挑出t个数,在保持元素相对顺序不变的情况下使得挑出的数字最大
     2、在保持元素相对顺序不变的前提下,将两个数组合并成一个数组,使得合并后的数组最大

原问题可以转化为:遍历两个数组挑选元素的个数,分别求出当前策略下2个问题的解,然后返回最大结果。
子问题1:可以借助栈来实现
遍历nums
<1>如果栈顶元素比当前元素小,弹出栈顶元素,直到1、栈空,2、剩余nums中的元素不足以填满t
<2>如果栈里元素不够t,则将当前元素压入栈中。
子问题2:与归并排序类似
分别比较两数组剩余数组的大小,将大的那个数组的当前数填入新数组。

这里需要注意比较的是剩余数组的大小,而非当前元素,因为当前元素相等时需要比较后面的元素,知道不相等,取比较大的那个数组中的当前元素

参考代码如下:

    public int[] maxNumber(int[] nums1, int[] nums2, int k) {
        int n=nums1.length;
        int m=nums2.length;
        int[] result=null;
        for(int i=0;i<=n&&i<=k;i++){
            int j=k-i;
            if(j>=0&&j<=m&&j<=k){
                result=max(result,merge(getMax(nums1,i),getMax(nums2,j)));
            }
        }
        return result;
    }
    public int[]max(int[]nums1,int[]nums2){
        if(nums1==null)
            return nums2;
        int n=nums1.length;
        for(int i=0;i<n;i++){
            if(nums1[i]<nums2[i])
                return nums2;
            if(nums1[i]>nums2[i])
                return nums1;
        }
        return nums1;
    }
    public int[]getMax(int[]nums,int len){
        if(len==0)
            return null;
        int n=nums.length;
        int[]temp=new int[n];
        int ri=0;
        for(int i=0;i<n;i++){
            while(ri>0&&ri+n-i>len&&temp[ri-1]<nums[i])
                ri--;
            if(ri<len)
                temp[ri++]=nums[i];
        }
        int[]result=new int[len];
        for(int i=0;i<len;i++){
            result[i]=temp[i];
        }
        return result;
    }
    public boolean greater(int[]nums1,int i,int[] nums2,int j){
        int n=nums1.length;
        int m=nums2.length;
        while(i<n&&j<m){
            if(nums1[i]<nums2[j])
                return false;
            else if(nums1[i]>nums2[j])
                return true;
            //相等
            i++;
            j++;
        }
        if(i<n)
            return true;
        else
            return false;
    }
    public int[]merge(int[]nums1,int[] nums2){
        if(nums1==null)
            return nums2;
        if(nums2==null)
            return nums1;
        int n=nums1.length;
        int m=nums2.length;
        int[]result=new int[n+m];
        int i=0,j=0,k=0;
        while(i<n&&j<m){
            if(greater(nums1,i,nums2,j)){
                result[k++]=nums1[i++];
            }
            else{
                result[k++]=nums2[j++];
            }

        }
        while(i<n)
            result[k++]=nums1[i++];
        while(j<m)
            result[k++]=nums2[j++];
        return result;
    }

参考链接:
http://bookshadow.com/weblog/2015/12/24/leetcode-create-maximum-number/
http://www.cnblogs.com/CarryPotMan/p/5384172.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值