题目描述:
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.
(给定两个长度为m和n并且由数字0-9组成的数组代表两个数。从两个数组中创建长度为K<=m+n的数字。必须保留来自同一数组的数字的相对顺序。返回一个k位数组。尽量优化时间和空间复杂度。)
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]
思路:分解问题:由两个数组中不改变先后顺序的数组成的k位最大数可以分解为两个问题。1.在一个数组中找到由数组中不改变先后顺序n位数组成的最大数。2.将两个数组所找出长度为n和k-n长度的最大数合并为一个最大数。
第一个问题利用一个栈,遍历所有元素,如果当前遍历元素大于栈顶元素,那么栈顶元素出栈,重复比较操作,直到遇到栈顶元素大于当前元素或栈空或者原数组中剩余数和栈中数字数目之和不大于n时,如果此时结果栈长度小于n,那么将该元素入栈。
第二个问题依次比较两个求得最大数组元素,假如num1当前元素大于num2当前元素,则将num1元素放入结果集,num2该元素继续和num1下一位元素比较,若num2空则将num1剩余元素全部放入结果集,反之。直到num1和num2均空。不过有一种特殊情况就是所比较的两元素相等,遇到这种情况就一直向后比较,直到遇到不相同的元素或者超出某一个数组的长度,将和较大不同数同数组的相同数入结果集,这种情况可以参考给出的例子nums1 = [6, 7],nums2 = [6, 0, 4],7比0大,所以nums1中的6先入站。最后比较两个数组取各种n值时组成的最大数找到结果即可。
public class Create_Maximum_Number {
//求出单个数组长度为k的最大数
public static ArrayList<Integer> getMax(int num[],int k)
{
ArrayList<Integer> result = new ArrayList<Integer>();
for(int i=0;i<num.length;i++)
{
while(result.size()>0&&num[i]>result.get(result.size()-1)&&(result.size()+num.length-i)>k)
{
result.remove(result.size()-1);
}
if(result.size()<k)
{
result.add(num[i]);
}
}
return result;
}
//将两个数组的最大数结合为一个最大数
public static ArrayList<Integer> Combine(ArrayList<Integer> num1,ArrayList<Integer> num2)
{
ArrayList<Integer> result = new ArrayList<Integer>();
while(num1.size()+num2.size()>0)
{
int flag = 0;
while(flag<num1.size()&&flag<num2.size()&&num1.get(flag)==num2.get(flag))
{
flag++;
}
if((flag<num1.size()&&flag<num2.size()&&num1.get(flag)>num2.get(flag))||flag+1>num2.size())
{
result.add(num1.get(0));
num1.remove(0);
}
else
{
if((flag<num1.size()&&flag<num2.size()&&num1.get(flag)<num2.get(flag))||flag+1>num1.size())
{
result.add(num2.get(0));
num2.remove(0);
}
}
}
return result;
}
//判断两个序列的大小
public static boolean judge(ArrayList<Integer> num1,ArrayList<Integer> num2)
{
if(num2.size()==0)
return true;
for(int i=0;i<num1.size();i++)
{
if(num1.get(i)>num2.get(i))
return true;
if(num1.get(i)<num2.get(i))
break;
}
return false;
}
public static int[] maxNumber(int[] nums1, int[] nums2, int k)
{
if(k>(nums1.length+nums2.length))
return null;
int result[] = new int[k];
ArrayList<Integer> maxList = new ArrayList<Integer>();
for(int i=0;i<=k;i++)
{
if(i>nums1.length||k-i>nums2.length)
continue;
if(judge((Combine(getMax(nums1,i),getMax(nums2,k-i))),maxList))
{
maxList = Combine(getMax(nums1,i),getMax(nums2,k-i));
}
}
for(int i=0;i<k;i++)
result[i] = maxList.get(i);
return result;
}
public static void main(String[] args) {
// int nums1[] = {3, 4, 6, 5};
// int nums2[] = {9, 1, 2, 5, 8, 3};
// int k = 5;
// int nums1[] = {6, 7};
// int nums2[] = {6, 0, 4};
// int k = 5;
// int[] nums1 = {3,9};
// int[] nums2 = {8,9};
// int k = 3;
//[7,3,8,2,5,6,4,4,0,6,5,7,6,2,0]
int[] nums1 = {2,5,6,4,4,0};
int[] nums2 = {7,3,8,0,6,5,7,6,2};
int k = 15;
int result[] = maxNumber(nums1,nums2,k);
for(int i=0;i<result.length;i++)
{
System.out.print(result[i]);
}
}
}