leetcode 321

问题

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:

1
2
3
4
5
6
Input:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
Output:
[9, 8, 6, 5, 3]

Example 2:

1
2
3
4
5
6
Input:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
Output:
[6, 7, 6, 0, 4]

Example 3:

1
2
3
4
5
6
Input:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
Output:
[9, 8, 9]

分析

求解这个问题首先要求解两个子问题。

  1. 给定一个数组 vector<int> nums,从中求出一个长度为 x 的子序列,使其所代表的数字最大。
  2. 给定两个数组,将其按序分配合并,返回最大可能的数组,要保证元素在新数组中相对位置与原数组相同。

NOTE: 这两个子问题的求解都比较典型和重要。merge的时间复杂度是 $O((n+m)^2)$ ,整体的时间复杂度$O(k(n+m)^2)$

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class Solution {
public:
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int n1 = nums1.size();
int n2 = nums2.size();

vector<int> ans = {};
for (int i = 0; i <= k; ++i) {
if (i > n1 || k-i > n2) continue;
vector<int> candi = mergeArr(getArr(nums1, i), getArr(nums2, k-i));
if (candi.size() > ans.size() ||
(candi.size() == ans.size() && candi > ans))
ans = candi;
}
return ans;
}
vector<int> getArr(vector<int> &nums, int x) {
if (x == 0) return {};
int to_pop = nums.size() - x;
vector<int> ret;
for (int a: nums) {
while (ret.size() != 0 && ret.back() < a && to_pop > 0) {
ret.pop_back();
to_pop--;
}
ret.push_back(a);
}
return vector<int>(ret.begin(), ret.begin()+x);
}

bool geater(vector<int> &a, int i, vector<int> &b, int j) {
while (i < a.size() && j < b.size()) {
if(a[i] > b[j]) return true;
if(a[i] < b[j]) return false;
i++;
j++;
}
if (i == a.size()) return false;
return true;
}
vector<int> mergeArr(vector<int> a, vector<int> b) {
int n = a.size() + b.size();
vector<int> ret(n);
for (int k = 0, i = 0, j = 0; k < n; ++k) {
if (geater(a, i, b, j))
ret[k] = a[i++];
else
ret[k] = b[j++];
}
return ret;
}

};