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]

给定两个数(用数组表示每一位),计算两个数合并后的最大k位数。

分析:

1、结果的k位可以是从第一个数组取0位,从第二个数组取k位;或者从第一个数组取1位,从第二个数组取k-1位;依次类推。从第一个数组取i位最大数x,从第二个数组取(k-i)位最大数y,再把x和y合并起来。

2、从一个数组中保持原顺序地取出k个数,使得这k个数组成最大的数字的方法是:

记结果数组为result,原数组为nums。从左往右遍历nums,①如果result不满k个数,那么把nums的一个数放入result中。②否则要考虑是否替换掉result中原有的数。从后往前遍历result数组,比result中比nums[i]小的数字都是应该替换掉的,除非nums剩下的数字不能够填满result。

代码:

class Solution {
public:
    vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
        
        int n=nums1.size(),m=nums2.size();
        vector<int> res;
        for(int i=0;i<=k;i++)
        {
            if(k-i>m) continue;
            if(i>n) break;
            vector<int> curNums1 = maxNumber(nums1,i);//从第一个数组中取i个
            vector<int> curNums2 = maxNumber(nums2,k-i);//从第二个数组中取k-i个
            vector<int> curNums = myMerge(curNums1,curNums2);//合并两个数组
            if(greater(curNums,0,res,0)) res=curNums;//如果这样分的结果比原来的大,更新
        }
        return res;
    }
    vector<int> maxNumber(vector<int>& nums,int k)//求一个数组中能组成的k位最大数
    {
        vector<int> result(k,0);
        int j=-1,n=nums.size();
        for(int i=0;i<n;i++)
        {
            while( j>=0 && (n-i)>=(k-j) && nums[i]>result[j] ) j--;
            if(j<k-1)
            {
                j++;
                result[j] = nums[i];
            }
        }
        return result;
    }
    vector<int> myMerge(vector<int>& nums1,vector<int>& nums2)//合并两个数组
    {
        int len1=nums1.size(),len2=nums2.size();
        vector<int> result(len1+len2);
        int i=0,j=0,k=0;
        while(k<len1+len2)
        {
            if(i<len1&&greater(nums1,i,nums2,j)) result[k++] = nums1[i++];
            else result[k++] = nums2[j++];
        }
        return result;
    }
    bool greater(vector<int>& nums1,int i,vector<int>& nums2,int j)//如果第一个数(从i往后)大于第二个数(从j往后),返回true
    {
        int len1=nums1.size(),len2=nums2.size();
        while(i<len1 && j<len2 && nums1[i]==nums2[j]){i++;j++;}
        if(i==len1) return false;
        if(j==len2) return true;
        return nums1[i]>nums2[j];
    }
};
时间复杂度:O(n*m*k)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值