拼接最大数
难度:
标签:
题目描述
You are given two integer arrays nums1
and nums2
of lengths m
and n
respectively. nums1
and nums2
represent the digits of two numbers. You are also given an integer k
.
Create the maximum number of length k <= m + n
from digits of the two numbers. The relative order of the digits from the same array must be preserved.
Return an array of the k
digits representing the answer.
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]
Constraints:
m == nums1.length
n == nums2.length
1 <= m, n <= 500
0 <= nums1[i], nums2[i] <= 9
1 <= k <= m + n
代码结果
运行时间: 72 ms, 内存: 16.8 MB
/*
* Problem: Given two integer arrays nums1 and nums2, representing the digits of two numbers,
* and an integer k, find the maximum number of length k that can be formed from digits of nums1 and nums2,
* while maintaining the relative order of digits from each array.
*
* Approach:
* 1. Create a helper function to find the maximum subsequence of a given length from a single array using Streams.
* 2. Iterate over all possible lengths for subsequences from both arrays such that their combined length is k.
* 3. Merge the two subsequences to form the largest possible number.
* 4. Compare the merged number with the current maximum and update if necessary.
*/
import java.util.Arrays;
import java.util.stream.IntStream;
public class SolutionStream {
public int[] maxNumber(int[] nums1, int[] nums2, int k) {
int m = nums1.length, n = nums2.length;
int[] maxSubsequence = new int[k];
for (int i = Math.max(0, k - n); i <= Math.min(k, m); i++) {
int[] subsequence1 = maxSubsequence(nums1, i);
int[] subsequence2 = maxSubsequence(nums2, k - i);
int[] candidate = merge(subsequence1, subsequence2);
if (greater(candidate, 0, maxSubsequence, 0)) {
maxSubsequence = candidate;
}
}
return maxSubsequence;
}
private int[] maxSubsequence(int[] nums, int k) {
int[] subsequence = new int[k];
int top = -1;
int remain = nums.length - k;
for (int num : nums) {
while (top >= 0 && subsequence[top] < num && remain > 0) {
top--;
remain--;
}
if (top < k - 1) {
subsequence[++top] = num;
} else {
remain--;
}
}
return subsequence;
}
private int[] merge(int[] nums1, int[] nums2) {
return IntStream.concat(IntStream.of(nums1), IntStream.of(nums2))
.boxed()
.sorted((a, b) -> b - a)
.mapToInt(i -> i)
.toArray();
}
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]);
}
}
解释
方法:
题解思路分为几个步骤:
1. 对于 nums1 和 nums2 分别生成所有可能的子序列(通过删除元素)的非降序排列。
2. 然后对于每个可能的 i(i 代表从 nums1 中选择的元素数量,k-i 代表从 nums2 中选择的元素数量),将 nums1 中的前 i 个元素和 nums2 中的前 k-i 个元素合并成最大的数。
3. 比较所有合并后的数,找到最大的那个。
时间复杂度:
O(m^2 + n^2 + k*min(m,k))
空间复杂度:
O(m^2 + n^2 + k)
代码细节讲解
🦆
为什么在生成最大子序列时选择使用单调栈,并且如何确保通过单调栈得到的序列是最大的?
▷🦆
在合并两个子序列以形成最大数时,如何处理两个序列的前缀相同时的判断逻辑?具体的,当`s1[i:] == s2[j:]`时,应该如何选择下一个数字?
▷🦆
在实际代码实现中,如何保持从同一数组中取出的数字的相对顺序不变?
▷相关问题
移掉 K 位数字
给你一个以字符串表示的非负整数 num
和一个整数 k
,移除这个数中的 k
位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。
示例 1 :
输入:num = "1432219", k = 3 输出:"1219" 解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。
示例 2 :
输入:num = "10200", k = 1 输出:"200" 解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。
示例 3 :
输入:num = "10", k = 2 输出:"0" 解释:从原数字移除所有的数字,剩余为空就是 0 。
提示:
1 <= k <= num.length <= 105
num
仅由若干位数字(0 - 9)组成- 除了 0 本身之外,
num
不含任何前导零