最大拼接数问题(Leetcode/C++)详细解释

class Solution {
public:
    vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
        // 读取nums数组的长度
        int m = nums1.size(),n = nums2.size();
        // 初始化一个整型向量,其中包含K个元素
        vector<int>maxSubsequence(k,0);
        // 返回最小值和最大值在start 和 end: 中两个数
        int start = max(0,k-n),end = min(k,m);
    //这里For循环的意思是第一个矩阵遍历0第二个矩阵遍历K然后第一个1第二个k-1这样就所有的数字都能遍历到
        for (int i = start;i <= end; i++){
            vector<int>subsequence1(MaxSubsequence(nums1,i));
            vector<int>subsequence2(MaxSubsequence(nums2,k-i));
            vector<int>curMaxSubsequence(merge(subsequence1,subsequence2));
            if(compare(curMaxSubsequence,0,maxSubsequence,0)>0){
                // 交换max和cur的值
                maxSubsequence.swap(curMaxSubsequence);
            }
        }
        //更新maxSubsequence
        return maxSubsequence;
    }
    // &引用传递符号,用来传递参数的值避免生成副本,提高运算效率,这里输入nums向量和K
    vector<int>MaxSubsequence(vector<int>&nums,int k){
        int length = nums.size();
        // 初始化向量为0,纬度K
        vector<int>stack(k,0);
        //初始化K纬度的0向量
        int top = -1;
        // 检查我们需要剩下多少数字
        int remain = length - k;
        for(int i = 0;i < length;i++){
            // 循环提取nums中的数字
            int num = nums[i];
            // 判断上一个数字是否小于后一个数字如果是那么删掉上一个数字重新在下面加入
            while(top >= 0 && stack[top] < num && remain > 0){
                top--;
                remain--;
            }
            // 把num值加入到stack中,第一个值加入,上面的判断,最后按顺序搜索出从大到小的数字
            //如果按照这种提取的数字个数不过,那么我们会直接将后面的数字压入栈中,remain是剩余数字数量,当remain为0时上面的while语句不执行。
            if (top < k-1 ){
                stack[++top] = num;
            }else{
                remain--;
            }
        }
        return stack;
    }
    vector<int>merge(vector<int>&subsequence1,vector<int>&subsequence2){
        int x = subsequence1.size(),y = subsequence2.size();
        if (x==0){
            return subsequence2;
        }
        // 合并数字 
        if (y == 0){
            return subsequence1;
        }
        // 合并的数字长度
        int mergeLength = x+y;
        vector<int> merged(mergeLength);
        // 纬度
        int index1 = 0, index2 = 0;
        for (int i = 0; i < mergeLength;i++){
            // 比较赋值X第一位大于Y第一位赋值x第一位,x第二位如果小于y第一位赋值y第一位
            //如果两个都相等那么,判断数组剩余长度剩余的多的先赋值
            if(compare(subsequence1,index1,subsequence2,index2)>0){
                merged[i] = subsequence1[index1++];
            }else{
                merged[i] = subsequence2[index2++];
            }
        }
        return merged;
    }
    int compare(vector<int>&subsequence1,int index1,vector<int>&subsequence2,int index2){
        int x = subsequence1.size(),y = subsequence2.size();
        while (index1<x&&index2<y){
            //两个数字的差距
            int difference = subsequence1[index1] - subsequence2[index2];
            //两个数差不为0
            if(difference!=0){
                // 返回deference值,大于0则x,这位数大于y,小于零则X小于y
                return difference;
            }
            index1++;
            index2++;
        }
        // 返回从数组中选区的两个数字个数差。
        //如果大于0说明x剩得多y少反之亦然
        //剩余长度大的优先赋值,这个我觉得无关紧要小的也可以赋值
        return(x -index1)-(y-index2);
    }

};
//总结:思路很简单,从两个数组中选取k个数字拼接成最大数字,并且这个k的数字的相对顺序不能变。相对顺序就是你从x数组中选择了3个数,这三个数字在原数组一定是第一个数在第二个前面依次排列,同理y数字选取的数字也是如此拼接后也是如此。所以我们数组遍历的条件就是前一个数字一定要保证比后一个大最后才能拼接出最大的数字,所以在两个数组中这样遍历首先判断选取个数是否大于x或y的长度如果大那么必有一种可能就是拼接的数字从两个数组中选取,如果小则会出现只从一种数组中选取数字的情况。那么遍历条件就是start = max(0,k-n),end = min(k,m);n,m是x,y数组的长度。遍历的时候直接按照从前到后,并且满足从小到大的顺序选择数字,如果无法选择,当然这两个选择不一定同时满足,这里就需要设置条件如果选择数字个数不够那么在最后直接压入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值