版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jining11/article/details/84311064
问题描述
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.
Note: You should try to optimize your time and space complexity.
Example 1:
Input:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
Output:
[9, 8, 6, 5, 3]
Example 2:
Input:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
Output:
[6, 7, 6, 0, 4]
Example 3:
Input:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
Output:
[9, 8, 9]
算法设计
可以分成三大部分来考虑,首先是分别从两个向量中提取长度为x的最大数字s1和长度为k-x的最大数字s2,之后是要将s1和s2合并成为最大的数字s3,最后是从所有可能的s3当中,抽取最大的那一个,并转换成vector返回。
主要思想:
- 从向量中提取某长度的最大数字使用了贪心法,因为只要一个数字的高位比另一个数字高,就一定比它要大,因此可以使用栈来不断更新高位的值。
- 将两个字符串合并使用了类似归并排序的思路,每次都看两个字符串的第一个元素的值谁更大。但要注意由于字符串并非是内部有序的,因此在遇到相等的情况时要一直往后找来决定选择哪一个。
代码实现
class Solution {
public:
//从num里面求取长为k的最大值
string get_maxnum (vector<int>& num, int k) {
string v = "";
char c;
if (k == 0) {
return v;
}
v.resize(k);
v[0] = char(num[0]+'0');
int j = 1;
for (int i = 1; i < num.size(); i++) {
c = char(num[i]+'0');
if (c > v[j-1]) {
while (c > v[j-1] && num.size()-i+j > k && j > 0) {
j--;
}
}
if (j < k) {
j++;
v[j-1] = c;
}
}
return v;
}
//获取两个向量按序能够组成的最长的串
string maxnumber(string nums1, string nums2) {
string s = "";
int m = nums1.size();
int n = nums2.size();
int i = 0, j = 0;
for (; i < m && j < n;) {
if (nums1[i] > nums2[j]) {
s += nums1[i];
i++;
}
else if (nums1[i] < nums2[j]) {
s += nums2[j];
j++;
}
else {
int ii = i, jj = j;
for(;;ii++,jj++) {
if (nums1.size() == ii || nums2[jj] > nums1[ii]) {
jj = ii+1;
break;
}
if (nums2.size() == jj || nums2[jj] < nums1[ii]) {
ii = jj+1;
break;
}
}
if (ii > jj) {
s += nums1[i];
i++;
}
else {
s += nums2[j];
j++;
}
}
}
return s+nums1.substr(i)+nums2.substr(j);
}
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int m = nums1.size();
int n = nums2.size();
string max = "";
int mm = m > k ? k:m;
int nn = n > k ? k:n;
string temp;
for (;mm >= 0; mm--) {
if (mm == k) {
temp = get_maxnum(nums1, mm);
}
else {
if (k-mm <= nn) {
temp = maxnumber(get_maxnum(nums1, mm), get_maxnum(nums2, k-mm));
}
else {
break;
}
}
max = max < temp ? temp:max;
}
for (;nn >= 0; nn--) {
if (nn == k) {
temp = get_maxnum(nums2, nn);
}
else {
if (k-nn <= mm) {
temp = maxnumber(get_maxnum(nums2, nn), get_maxnum(nums1, k-nn));
}
else {
break;
}
}
max = max < temp ? temp:max;
}
std::vector<int> v;
for (auto c:max) {
v.push_back(c-'0');
}
return v;
}
};
这次被一个无比智障的bug坑了很久,就是我居然直接拿数字和字符比较,然后就得到了9 < '0’这种无比神奇的结果。不过也有收获,第一次用了string的resize方法。本来以为这个算法笨重无比,但最后居然结果还不错。。。