问题描述:
Given two arrays of length m
and n
with digits 0-9
representing two numbers. Create the maximum number of length k <= m + n
from digits of the two. The relative order of the digits from the same array must be preserved. Return an array of the k
digits. You should try to optimize your time and space complexity.
Example 1:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
return [9, 8, 6, 5, 3]
Example 2:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
return [6, 7, 6, 0, 4]
Example 3:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
return [9, 8, 9]
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
问题分析:
问题要求从两个数组中选择k个数字,使得新组成数字是最大的,并且保证选择的数字不改变在原来数组中的相对顺序。
问题可以转化为两个子问题:
1、从数组nums中挑出t个数,在保持元素相对顺序不变的情况下使得挑出的数字最大 2、在保持元素相对顺序不变的前提下,将两个数组合并成一个数组,使得合并后的数组最大
原问题可以转化为:遍历两个数组挑选元素的个数,分别求出当前策略下2个问题的解,然后返回最大结果。
子问题1:可以借助栈来实现
遍历nums
<1>如果栈顶元素比当前元素小,弹出栈顶元素,直到1、栈空,2、剩余nums中的元素不足以填满t
<2>如果栈里元素不够t,则将当前元素压入栈中。
子问题2:与归并排序类似
分别比较两数组剩余数组的大小,将大的那个数组的当前数填入新数组。
这里需要注意比较的是剩余数组的大小,而非当前元素,因为当前元素相等时需要比较后面的元素,知道不相等,取比较大的那个数组中的当前元素
参考代码如下:
public int[] maxNumber(int[] nums1, int[] nums2, int k) {
int n=nums1.length;
int m=nums2.length;
int[] result=null;
for(int i=0;i<=n&&i<=k;i++){
int j=k-i;
if(j>=0&&j<=m&&j<=k){
result=max(result,merge(getMax(nums1,i),getMax(nums2,j)));
}
}
return result;
}
public int[]max(int[]nums1,int[]nums2){
if(nums1==null)
return nums2;
int n=nums1.length;
for(int i=0;i<n;i++){
if(nums1[i]<nums2[i])
return nums2;
if(nums1[i]>nums2[i])
return nums1;
}
return nums1;
}
public int[]getMax(int[]nums,int len){
if(len==0)
return null;
int n=nums.length;
int[]temp=new int[n];
int ri=0;
for(int i=0;i<n;i++){
while(ri>0&&ri+n-i>len&&temp[ri-1]<nums[i])
ri--;
if(ri<len)
temp[ri++]=nums[i];
}
int[]result=new int[len];
for(int i=0;i<len;i++){
result[i]=temp[i];
}
return result;
}
public boolean greater(int[]nums1,int i,int[] nums2,int j){
int n=nums1.length;
int m=nums2.length;
while(i<n&&j<m){
if(nums1[i]<nums2[j])
return false;
else if(nums1[i]>nums2[j])
return true;
//相等
i++;
j++;
}
if(i<n)
return true;
else
return false;
}
public int[]merge(int[]nums1,int[] nums2){
if(nums1==null)
return nums2;
if(nums2==null)
return nums1;
int n=nums1.length;
int m=nums2.length;
int[]result=new int[n+m];
int i=0,j=0,k=0;
while(i<n&&j<m){
if(greater(nums1,i,nums2,j)){
result[k++]=nums1[i++];
}
else{
result[k++]=nums2[j++];
}
}
while(i<n)
result[k++]=nums1[i++];
while(j<m)
result[k++]=nums2[j++];
return result;
}
参考链接:
http://bookshadow.com/weblog/2015/12/24/leetcode-create-maximum-number/
http://www.cnblogs.com/CarryPotMan/p/5384172.html