m == nums1.length
n == nums2.length
1 <= m, n <= 500
0 <= nums1[i], nums2[i] <= 9
1 <= k <= m + n
二、解题思路
- 创建一个辅助函数
monoInc
,该函数能够从一个数组中找出长度为k
的最大单调递增子序列。这个子序列是在保持原数组元素相对顺序的情况下得到的。 - 创建另一个辅助函数
merge
,该函数能够合并两个单调递增的数组,并返回一个长度为k
的最大单调递增数组。 - 在
maxNumber
函数中,遍历所有可能的从nums1
中取i
个元素,从nums2
中取k-i
个元素的情况(i
的取值范围是0
到k
,并且要满足i <= nums1.length
和k-i <= nums2.length
),然后使用merge
函数合并这些元素,并保留合并后的最大数组。
三、具体代码
class Solution {
public int[] maxNumber(int[] nums1, int[] nums2, int k) {
int m = nums1.length, n = nums2.length;
int[] ans = new int[k];
for (int i = Math.max(0, k - n); i <= k && i <= m; ++i) {
int[] candidate = merge(monoInc(nums1, i), monoInc(nums2, k - i), k);
if (greater(candidate, 0, ans, 0)) {
ans = candidate;
}
}
return ans;
}
private int[] monoInc(int[] nums, int k) {
int n = nums.length;
int[] res = new int[k];
for (int i = 0, j = 0; i < n; ++i) {
while (n - i > k - j && j > 0 && res[j - 1] < nums[i]) {
--j;
}
if (j < k) {
res[j++] = nums[i];
}
}
return res;
}
private int[] merge(int[] nums1, int[] nums2, int k) {
int[] res = new int[k];
for (int i = 0, j = 0, r = 0; r < k; ++r) {
res[r] = greater(nums1, i, nums2, j) ? nums1[i++] : nums2[j++];
}
return res;
}
private boolean greater(int[] nums1, int i, int[] nums2, int j) {
while (i < nums1.length && j < nums2.length && nums1[i] == nums2[j]) {
++i; ++j;
}
return j == nums2.length || (i < nums1.length && nums1[i] > nums2[j]);
}
}
在这段代码中:
-
monoInc
函数通过贪心算法,维护一个单调递增的序列。 -
merge
函数比较两个单调递增序列的元素,并合并成一个新的单调递增序列。 -
greater
函数比较两个序列的元素,如果第一个序列在某个位置上的元素更大,或者第二个序列已经结束,则返回true
。 -
maxNumber
函数遍历所有可能的组合,并保留合并后的最大数组。
四、时间复杂度和空间复杂度
1. 时间复杂度
-
maxNumber
函数:- 外层循环的次数取决于
nums1
和nums2
的长度以及k
的值,最坏情况下,循环次数为k
。 - 在每次循环中,我们调用
monoInc
两次和merge
一次。 -
greater
函数在merge
中被调用k
次。
- 外层循环的次数取决于
-
monoInc
函数:- 对于每个数组
nums
,我们进行一次遍历,时间复杂度为O(n)
,其中n
是数组的长度。 - 在每次遍历中,可能需要执行一个内部循环来移除不满足条件的元素,最坏情况下,内部循环可能执行
k
次。 - 因此,
monoInc
函数的时间复杂度为O(nk)
。
- 对于每个数组
-
merge
函数:- 这个函数对两个数组合并,每个数组长度为
k
,因此时间复杂度为O(k)
。 - 在合并过程中,我们调用了
greater
函数,其时间复杂度在最坏情况下为O(k)
。
- 这个函数对两个数组合并,每个数组长度为
-
greater
函数:- 这个函数比较两个数组的元素,最坏情况下,它需要遍历整个数组,时间复杂度为
O(k)
。
- 这个函数比较两个数组的元素,最坏情况下,它需要遍历整个数组,时间复杂度为
综合上述分析,总的时间复杂度为: O(k * (O(mk) + O(nk) + O(k) + O(k)))
= O(k * (mk + nk + 2k))
= O(k^2 * (m + n + 2))
= O(k^2 * (m + n))
。
2. 空间复杂度
-
maxNumber
函数:- 需要常数空间来存储变量
m
、n
、ans
、i
等。 - 需要额外空间来存储每次
merge
函数的返回结果。
- 需要常数空间来存储变量
-
monoInc
函数:- 需要一个长度为
k
的数组res
来存储结果。
- 需要一个长度为
-
merge
函数:- 需要一个长度为
k
的数组res
来存储合并后的结果。
- 需要一个长度为
-
greater
函数:- 只需要常数空间。
综合上述分析,总的空间复杂度为:O(k)
,因为最大的空间占用是在monoInc
和merge
函数中创建的长度为k
的数组。