- 拼接最大数-枚举所有组-单调栈+贪心算法
给定长度分别为 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;
}