Leetcode題解:用字串快速解決Create Maximum Number問題
阿新 • • 發佈:2018-12-05
問題描述
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方法。本來以為這個演算法笨重無比,但最後居然結果還不錯。。。