📌  相关文章
📜  来自两个给定数组的子序列的最大K位数字(1)

📅  最后修改于: 2023-12-03 14:55:29.767000             🧑  作者: Mango

最大K位数字

问题描述

给出两个数组 num1num2,从这两个数组中分别取出一个长度为 mn 的子序列,合并成一个大小为 m + n 的新数组并且使得新数组中的数字最大。需要返回这个最大数字。

示例
输入:
num1 = [3, 4, 6, 5]
num2 = [9, 1, 2, 5, 8, 3]
k = 5
输出:
95343
思路

这道题目可以使用贪心算法来解决。而在贪心箭头正在右移的时候,可以利用类似于归并排序的方式,求出所有可能的结果。具体实现时,我们可以用两个指针分别在num1和num2中试探选取数字大小的范围,然后再用归并排序的方式合并。

假设num1数组中选择了i个数字,那么num2中就需要选择 k - i 个数字。然后我们将num1的前 i 个数字和num2的前 k - i 个数字合并,得到一个新的数组candidate。对于 candidate 数组, 其第一个数字不是num1中的第i个数字,就是num2中的第k - i个数字。为了找到这个新数组的最大值,需要保证其第一个数字是最大值。因此需要比较num1中从i开始到结尾,和num2中从k-i处到结尾的数组,取其中较大值拼接到 candidate 数组的第一个数字上,然后再重新从新数组candidate中选i和k - i个数字作为num1和num2的下一次选项。

在这个过程中,需要注意特殊情况,如num2数组只包含一个数字时,要么使用这个数字作为结果,要么一定要从num1中选出k个数字作结果。

代码实现
def get_max_num(num1, num2, k):
    def merge(num1, num2):
        res = []
        while num1 or num2:
            if num1 > num2:
                res.append(num1.pop(0))
            else:
                res.append(num2.pop(0))
        return res

    m, n = len(num1), len(num2)

    if m > n:
        return get_max_num(num2, num1, k)

    if n == 0:
        return "".join([str(x) for x in num1[:k]])

    if k >= n + m:
        return "".join([str(x) for x in sorted(num1 + num2, reverse=True)])

    l, r = max(0, k - n), min(m, k)
    candidate = merge(num1[:r], num2[:k-r])
    ans = [0] * k
    for i in range(k):
        if candidate > ans:
            ans = candidate.copy()
        if len(num1) < l:
            break
        if i == k-1:
            ans = candidate.copy()
            break
        idx = num1.index(max(num1[l:min(len(num1), m-k+i+1)]))
        candidate.pop(0)
        candidate.append(num1[idx])
        l = idx + 1
        r = k - l
        candidate = merge(candidate, num2[:r])
    return "".join([str(x) for x in ans])
参考资料

LeetCode题解:321. Create Maximum Number