难度: Hard
原题连接
内容描述
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]
思路 1 - 时间复杂度: O((m+n)^2 * max(m,n))- 空间复杂度: O(m+n)******
- 一共k位digit,我们可以先确定从nums1里面取i位,那么从nums2肯定就是取k-i位
- 然后我们确定了从nums1里面取i位的话,就可以算出所能取得的长度为i的最大子序列lis1,相应的也可以算出从nums2取得的长度为k-i的最大子序列lis2
- 然后我们用双指针依次从lis1和lis2中取较大的那个数就可以了,不停更新res
Note:
- i至少需要k - len(nums2),否则digit不够, 但是如果k - len(nums2)小于0的话,i还是要从0开始取
- i最多取到k,但是因为num1也有长度限制,所以如果k > len(nums1)的时候,i最多取len(nums1)
参考
假设num1 和 nums2的长度分别为m和n,因为这里k最大可以为m+n,getLis函数的时间复杂度为O(N),max(lis1, lis2).pop(0)
的时间复杂度为O(N)(因为需要重新排列),
所以总的时间复杂度为O([m+n] * [m + n + k * max(m,n)])
,也可以直接看为O((m+n)^2 * max(m,n))
beats 46.87%
class Solution:
def maxNumber(self, nums1, nums2, k):
"""
:type nums1: List[int]
:type nums2: List[int]
:type k: int
:rtype: List[int]
"""
def getLis(nums, k):
res, n = [], len(nums)
for i in range(n):
while res and len(res) + n - i > k and res[-1] < nums[i]:
res.pop()
if len(res) < k:
res.append(nums[i])
return res
res = [0] * k
for i in range(max(0, k-len(nums2)), min(k, len(nums1)) + 1):
lis1 = getLis(nums1, i)
lis2 = getLis(nums2, k-i)
res = max(res, [max(lis1, lis2).pop(0) for _ in range(k)])
return res
思路 2 - 时间复杂度: O((m+n)^2)- 空间复杂度: O(m+n)******
我们可以省去max(lis1, lis2).pop(0)
重新排列的时间,用deque就可以了
此时总的时间复杂度为O([m+n] * [m + n + (m+n) + k])
,也可以直接看为O((m+n)^2)
beats 50%
class Solution:
def maxNumber(self, nums1, nums2, k):
"""
:type nums1: List[int]
:type nums2: List[int]
:type k: int
:rtype: List[int]
"""
def getLis(nums, k):
res, n = [], len(nums)
for i in range(n):
while res and len(res) + n - i > k and res[-1] < nums[i]:
res.pop()
if len(res) < k:
res.append(nums[i])
return res
res = [0] * k
for i in range(max(0, k-len(nums2)), min(k, len(nums1)) + 1):
lis1 = getLis(nums1, i)
lis2 = getLis(nums2, k-i)
lis1, lis2 = list(map(collections.deque, [lis1, lis2]))
res = max(res, [max(lis1, lis2).popleft() for _ in range(k)])
return res