321 拼接最大数

题目描述:
给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。
求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。
说明: 请尽可能地优化你算法的时间和空间复杂度。

示例 1:
输入:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
输出:
[9, 8, 6, 5, 3]

示例 2:
输入:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
输出:
[6, 7, 6, 0, 4]

示例 3:
输入:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
输出:
[9, 8, 9]

方法1:
主要思路:
(1)理清几个关键点:
(2)总长为 k 的数字若是又两个数组组合,若 数组一中使用 s 个,则数组二中使用 k-s 个,且 s 个元素组成的子序列是数组一中的长度为 s的最大子序列,同时 k-s 个元素组成的子序列是数组二中的长度为 k-s 的最大子序列;
(3)那么,就相当于需要找出两个数组中各种长度组合下的最大子序列,然后合并两个最大子序列即可;
(4)定义了找某个数组的某个长度的最大子序列的函数,以及判断两个子序列大小的函数;

class Solution {
public:
	//在给定的数组中找给定长度的最大子序列
    vector<int> max_sequence_k(vector<int>& num,int len){
        vector<int> res;
        for(int i=0;i<num.size();++i){
        	//第三个条件保证了获得数组长度最小为给定的长度len
            while(!res.empty()&&res.back()<num[i]&&i+len-res.size()<num.size()){
                res.pop_back();
            }
            res.push_back(num[i]);
        }
        return vector<int>(res.begin(),res.begin()+len);//返回需要的长度的数组
    }
    //判断两个数组的某个子数组的大小,子数组的起始位置给出
    bool compare(vector<int>& lhs,int left,vector<int>& rhs,int right){
        while(left<lhs.size()&&right<rhs.size()){//判断大小
            if(lhs[left]>rhs[right]){
                return true;
            }
            else if(lhs[left]<rhs[right]){
                return false;
            }
            //当前数字等于的情形下,接着向后比较
            ++left;
            ++right;
        }
        if(left==lhs.size()){//先遍历完的数组较小处理
            return false;
        }
        return true;
    }
    vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
        vector<int>res(k,-1);//存储结果,初始化为-1
        int n=k-nums2.size();
        int len=(n)<0?0:n;//数组一的子序列的长度最小为多少
        int end_len=nums1.size()<k?nums1.size():k;//数组一的子序列的长度最大为多少
        while(len<=end_len){//遍历各种可能的长度组合
        	//获得两个指定长度的最大子序列
            vector<int> tmp1=max_sequence_k(nums1,len);
            vector<int> tmp2=max_sequence_k(nums2,k-len);
            int i=0,j=0;
            int pos=0;
            //合并两个最大子序列
            vector<int> tmp(k);
            while(i<len||j<k-len){
                if(compare(tmp1,i,tmp2,j)){
                    tmp[pos++]=tmp1[i++];
                }
                else{
                    tmp[pos++]=tmp2[j++];
                }
            }
            //更新可能的最大的结果
            res = compare(tmp,0,res,0) ? tmp : res;
            ++len;//遍历下一种长度组合
        }
        return res;
    }
};
上一篇:反转整数


下一篇:康托展开