给定长度分别为 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]
代码
class Solution {public int[] maxNumber(int[] nums1, int[] nums2, int k) {int m=nums1.length,n=nums2.length;int[] res=new int[k];int s=Math.max(0,k-n),end=Math.min(k,m);for(int i=s;i<=end;i++)//遍历nums1和nums2不同取数情况返回的最大数组,返回最大的结果{int[] cur=merge(getMaxNumber(nums1, i),getMaxNumber(nums2, k-i));if(comp(cur,0,res,0))res=cur;}return res;}public boolean comp(int[] nums1,int p1 ,int[] nums2, int p2) {
//比较两个序列,如果前面元素都相同,则长度大的较大if(p2>=nums2.length) return true;if(p1>=nums1.length) return false;if(nums1[p1]>nums2[p2]) return true;if(nums1[p1]<nums2[p2]) return false;return comp(nums1, p1+1, nums2, p2+1);}public int[] merge(int[] nums1, int[] nums2) {int n=nums1.length,m=nums2.length;int cur=0,p1=0,p2=0;int []ret=new int[n+m];while (p1<n||p2<m)//合并两个数组{if(comp(nums1,p1,nums2,p2))ret[cur++]=nums1[p1++];else ret[cur++]=nums2[p2++];}return ret;}public int[] getMaxNumber(int[] nums1, int k) {//单调栈找出单个数组的最大排列int n=nums1.length,rem=n-k,top=-1;int[] stack=new int[k];for(int i=0;i<n;i++){int cur=nums1[i];while (top>=0&&cur>stack[top]&&rem>0){top--;rem--;}if(top<k-1)stack[++top]=cur;else rem--;//可删除的额度减一,当可删除的额度用尽,将不能再移除元素(为了保证返回数组的长度)}return stack;}
}