博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面试题解 | 创建最大数
阅读量:6705 次
发布时间:2019-06-25

本文共 4704 字,大约阅读时间需要 15 分钟。

专栏 | 九章算法

网址 | http://www.jiuzhang.com

创建最大数

题目描述

给出两个长度分别是m和n的数组来表示两个大整数,数组的每个元素都是数字0-9。从这两个数组当中选出k个数字来创建一个最大数,其中k满足k <= m + n。选出来的数字在创建的最大数里面的位置必须和在原数组内的相对位置一致。返回k个数的数组。你应该尽可能的去优化算法的时间复杂度和空间复杂度。

样例

给出 nums1 = [3, 4, 6, 5], nums2 = [9, 1, 2, 5, 8, 3], k = 5返回 [9, 8, 6, 5, 3]给出 nums1 = [6, 7], nums2 = [6, 0, 4], k = 5返回 [6, 7, 6, 0, 4]给出 nums1 = [3, 9], nums2 = [8, 9], k = 3返回 [9, 8, 9]复制代码

算法分析

本题要求从两个数组中选择k个数字来创建最大数,同时要求保持数字在原数组中的相对位置。我们容易想到的是可以分别在两个 数组中选择x和k-x个数字,再通过将选择出的数字合并成一个最大数的算法。因此,我们首先来解决问题1。

问题一

如何从一个数组中选择k个数,组一个最大数

对于这个问题,容易想到如果越大的数字在结果中的位置越靠前(即在高位上),那么最终得到的结果越大。所以我们应该尽量将大的数字放置在结果数组的头部。但是有一个条件需要考虑,即剩余未选择的数的个数能否保证有合法解。因此,这个问题可以借助栈和贪心算法来实现,具体步骤如下:

1.如果栈不为空,同时栈顶元素比当前元素小,同时,剩余的元素大于等于k个,那么弹出栈顶元素;

直到 栈空或者 栈顶元素大于当前元素 或者 剩余元素不足k个;

2.同时如果栈内元素小于k,则将当前元素压入栈中;

我们可以利用数组来模拟栈,同时设置变量drop记录已经出栈的元素个数,具体代码如下:

//数组中选k个数组成的最大数  vector 
maxVec(vector
& num, int k){ int len = num.size(); int drop = len - k; vector
res; for(int i = 0; i < len ; i++){ while(res.size() > 0 && drop > 0 && res[res.size() - 1] < num[i]){ res.erase(res.end() - 1); drop --; } res.push_back(num[i]); } res.resize(k); return res; }复制代码

问题2

假设两个数组分别有m和n个元素,如何组成一个k = m+n 的最大数?

这个问题想法比较直观,在选取数字的时候,我们只需要选择尽量大的数字在前面即可,因此我们会选择两个数组头部元素中比较大的一个。但是有一种情况需要注意,当两个数组头部的元素一样大的时候,我们需要一直比较,直到选择出比较大的数组,选择该数组的头部元素。

1.比较两个数组大小的代码如下:

int findmax(vector
&num1, vector
& num2){ int len1 = num1.size(); int len2 = num2.size(); int i = 0,j = 0; while(i < len1 && j < len2 &&num1[i] == num2[j]){ i++;j++; } if(i < len1 && j < len2) return num1[i] < num2[j]; else if(i == len1) return 1; else return 0; }复制代码

2.两个长度分别为m和 n的数组组成k=m+n的最大数的代码如下:

// 两个数组组成的最大数   vector 
maxRes(vector
& nums1, vector
& nums2){ int len1 = nums1.size(); int len2 = nums2.size(); vector
res; while(nums1.size()||nums2.size()){ int tmp = findmax(nums1 ,nums2); if(tmp) { res.push_back(nums2[0]); nums2.erase(nums2.begin()); }else{ res.push_back(nums1[0]); nums1.erase(nums1.begin()); } } return res; }复制代码

问题3

原问题:如果两个数组长度分别为m和n,如何能够构建k <= m+n 的最大数?

我们把k个数分成两部分,i和 k-i ,分别从两个数组中选择i和k-i个数字构成的最大值,之后利用问题2中的方法将两个最大值合并,就得到了最终的结果。代码如下:

vector maxNumber(vector& nums1, vector& nums2, int k) { vector vec1; vector vec2; vector tmp; vector res(k,0); int m = nums1.size(); int n = nums2.size(); for(int i = max(0,k-n); i <= min(m,k) ; i++){ vec1 = maxVec(nums1, i); vec2 = maxVec(nums2, k-i); tmp = maxRes(v1,v2); if(findmax(res,tmp)) res = tmp; } return res; }

参考程序

class Solution {public:   /**    * @param nums1 an integer array of length m with digits 0-9    * @param nums2 an integer array of length n with digits 0-9    * @param k an integer and k <= m + n    * @return an integer array    */       //数组中选k个数组成的最大数   vector 
maxVec(vector
& num, int k){ int len = num.size(); int drop = len - k; vector
res; for(int i = 0; i < len ; i++){ while(res.size() > 0 && drop > 0 && res[res.size() - 1] < num[i]){ res.erase(res.end() - 1); drop --; } res.push_back(num[i]); } res.resize(k); return res; } int findmax(vector
&num1, vector
& num2){ int len1 = num1.size(); int len2 = num2.size(); int i = 0,j = 0; while(i < len1 && j < len2 &&num1[i] == num2[j]){ i++;j++; } if(i < len1 && j < len2) return num1[i] < num2[j]; else if(i == len1) return 1; else return 0; } vector
maxNumber(vector
& nums1, vector
& nums2, int k) { vector
vec1; vector
vec2; vector
tmp; vector
res(k,0); int m = nums1.size(); int n = nums2.size(); for(int i = max(0,k-n); i <= min(m,k) ; i++){ vec1 = maxVec(nums1, i); vec2 = maxVec(nums2, k-i); tmp = maxRes(v1,v2); if(findmax(res,tmp)) res = tmp; } return res; }};复制代码

这样的话,我们需要k次分割,每次分割构建最大值的时间复杂度是O(mn)的(问题2中比较大小的复杂度)。这样的话,总的时间复杂度是O(kmn)的。

面试官角度分析

这道题目属于medium难度的一类,主要考察面试者的分治思想。面试者给出上述算法即可达到hire的程度

欢迎关注我的微信公众号:九章算法(ninechapter)。
精英程序员交流社区,定期发布面试题、面试技巧、求职信息等

转载地址:http://iublo.baihongyu.com/

你可能感兴趣的文章
bufferedimage 转换成 inputstream并保存文件
查看>>
IntelliJ Idea13无法创建maven模板
查看>>
数组和集合的相互转换
查看>>
sql STUFF用法
查看>>
BZOJ3346 : Ural1811 Dual Sim Phone
查看>>
i++与++i 辨析
查看>>
WebService 之 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性。...
查看>>
ImportError: The _imagingft C module is not installed
查看>>
李洪强iOS经典面试题144-数据存储
查看>>
svn 和 git的区别
查看>>
五一游
查看>>
iOS后台解析
查看>>
Android View 深度分析requestLayout、invalidate与postInvalidate
查看>>
3.操作系统简单介绍 操作系统发展历史 批处理分时系统 操作系统是什么 操作系统对文件的抽象 进程 虚拟内存是什么 操作系统作用 操作系统功能...
查看>>
五花八门的main()
查看>>
PHP中的正则表达式及模式匹配
查看>>
当爬虫被拒绝时(Access Denied) - 风中之炎 - 博客园
查看>>
今天是多特殊
查看>>
tomcat的webappclassloader中一个奇怪的异常信息
查看>>
Java语言与C++语言的差异总结
查看>>