321. 拼接最大数-枚举所有组-单调栈+贪心算法

  1. 拼接最大数-枚举所有组-单调栈+贪心算法

给定长度分别为 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]

对于这一题,关键点在哪呢,比如,我们现在要组合得到一个最大的数,那么我们知道从给定的两个数组中我们怎么去组合呢
假设第一个数组八个数字
第二个数组九个数字
现在从第一个取三个数第二个取三个数,取的这三个数,应该是最大的三位数,主要在于这个推论。
当我们知道这个推论之后呢,我们的目标就变成了,取出所有的组合,然后拼接出这些组合的最大数,再从这些最大数中找到最大的那一个,解题代码如下:



/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

 void  monotone_stack(int *nums,int count,int *s,int numsSize){
     int top=0;
     for(int i=0;i<numsSize;i++){
        // printf("top %d ",top);
         if(i==0){
             s[top++]=nums[i];
             
         }
         else{
             if(top>=1)
               while(top>=1&&nums[i]>s[top-1]&&numsSize-i>=count-top+1){
                 top--;

             }
             if(top<count){
                  s[top++]=nums[i];

             }

         }
     }


 }
 void print(int *nums,int numsSize){
      for(int i=0;i<numsSize;i++){
          printf("%d ",nums[i]);
      }

 }

 void find_max(int *ret,int k,int *s1,int *s2,int n1,int n2){
     int p1=0,p2=0;
     int i=0;
     for(;i<k;){

         
         if(p1==n1||p2==n2){
            
             break;
         }
         else{
             if(s1[p1]>s2[p2]){
              
                 ret[i]=s1[p1];
                 p1++;
                 i++;

             }
             else if(s1[p1]<s2[p2]){
                
                 ret[i]=s2[p2];
                 p2++;
                   i++;

             }
              else if(s1[p1]==s2[p2]){
                 
                    //   ret[i]=s1[p1];
                    // p1++;
                    
                      int po1=p1;
                      int po2=p2;
                      while(s1[po1]==s2[po2]){
                          po1++;
                          po2++;
                          if(po1==n1){
                              break;
                          }
                           if(po2==n2){
                              break;
                          }
                      }
                    
                      if(po1==n1){
                         
                              ret[i]=s2[p2];
                              p2++;
                                i++;

                      }
                      else if(po2==n2){
                        
                            ret[i]=s1[p1];
                        p1++;
                       i++;

                      }
                      else{

                      if(s1[po1]>s2[po2]){
                               ret[i]=s1[p1];
                                p1++;
                                  i++;
                           
                               // printf(" %d i %d ",ret[i],i);
                              

                          }
                          if(s1[po1]<s2[po2]){
                               
                               ret[i]=s2[p2];
                                p2++;
                                  i++;
                               

                          }

                      }

                  
                   

              }
         }
        

     }
     while(p1!=n1){
         ret[i++]=s1[p1++];

     }
      while(p2!=n2){
         ret[i++]=s2[p2++];

     }
     for(int i=0;i<k;i++){
         printf("-%d ",ret[i]);
     }
    

 }
int* maxNumber(int* nums1, int nums1Size, int* nums2, int nums2Size, int k, int* returnSize){
    int *s1=(int *)malloc(sizeof(int)*nums1Size);
    int *s2=(int *)malloc(sizeof(int)*nums2Size);
    int *re=(int *)malloc(sizeof(int)*k);
     int *ret=(int *)malloc(sizeof(int)*k);
    *returnSize=k;
    int pz=0;

    for(int i=1;i<=nums1Size&&i<=k;i++){
        if(nums2Size>=k-i){
            monotone_stack(nums1,i,s1,nums1Size);
            monotone_stack(nums2,k-i,s2,nums2Size);
            printf("||");
          //  print(s1,i);
           // print(s2,k-i);
            if(pz==0){
                 find_max(re,k,s1,s2, i, k-i);
                 pz=1;
            }
            else{
                 find_max(ret,k,s1,s2, i, k-i);
                 for(int j=0;j<k;j++){
                     if(ret[j]>re[j]){
                         for(int kz=0;kz<k;kz++){
                             re[kz]=ret[kz];

                         }
                         break;
                     }
                     if(ret[j]<re[j]){
                         break;
                     }

                 }

            }
           
        }

    }
    return re;
    





}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值