Leetcode 321. 拼接最大数
比较复杂,但是比较好理解的一种方法。加了详细的注释,方便日后复习,也希望能帮到其他小伙伴,如有错误,欢迎指正!
class Solution:
def maxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:
# m和n分别表示nums1和nums2的长度
m = len(nums1)
n = len(nums2)
# 初始化最大的栈
maxSequence = [0] * k
"""x、y是从nums1中和nums2中抽出的子序列长度,我们需要遍历所有可能的x、y的值;
寻找那个最大的sequence,x、y的值有一个限制,x + y = k;
我们需要尽可能地减少x和y可能的值,start和end是从nums1抽出元素数量的最小值和最大值;
我们这里将i作为x,那么y=k-i"""
start = max(0, k - n)
end = min(k, m)
# 开始遍历所有可能的x和y的值,寻找最优的解
for i in range(start, end + 1):
# 设想我们已经确定了x和y,那么我们需要分别找到nums1和nums2的最大序列
subsequence1 = self.getMaxSubsequence(nums1, i)
subsequence2 = self.getMaxSubsequence(nums2, k - i)
# 按照getMaxSubsequence方法分别求出的最大序列融合后一定也是当前x和y的组合中最大的的序列
curMax = self.merge(subsequence1, subsequence2)
# 如果当前curMax比之前的序列都大,就替换
if self.trans_to_num(curMax) > self.trans_to_num(maxSequence):
maxSequence = curMax
return maxSequence
# 将序列转成数字,方便比较大小
def trans_to_num(self,maxSequence):
num = ""
for i in maxSequence:
num += str(i)
return int(num)
def getMaxSubsequence(self, nums, k):
stack = []
needToDelete = len(nums) - k
# 生成一个单调递减的栈,我们只需要保证该栈中的每个元素都是该位置所能选到的最大元素即可
for num in nums:
"""寻找当前num所在的位置,即需要满足num比栈顶元素小,如果num比栈顶元素更大,那就把栈顶元素删掉;
但是删除栈顶元素的前提是stack不为空且 允许删除的元素仍 > 0;
注意stack不为空的判断要放在stack[-1] < num的前面;"""
while needToDelete > 0 and stack and stack[-1] < num:
stack.pop()
needToDelete -= 1
stack.append(num)
# stack中的元素不一定是k个,我们只需要取最大的,所以取前k个元素即可
return stack[:k]
def merge(self,seq1,seq2):
# 这个方法写的质量不高,全是if-else,但是这是比较好理解的一种方式,如果这种方式理解了可以换其他更优的方式
res = []
# 只要两个序列中任意一个不为空,就一直遍历
# 融合的原则就是在不改变序列顺序的前提下,往res中添加seq1或seq2中的头元素;
# 每次往res中添加元素都选最大的,如果一样大,就添加下一个元素更大的,如果seq1和seq2完全一样,那就无所谓了,随便添加哪个都行
while seq1 or seq2:
if seq1:
first_seq1 = seq1[0]
else:
first_seq1 = 0
if seq2:
first_seq2 = seq2[0]
else:
first_seq2 = 0
if first_seq1 > first_seq2:
res.append(first_seq1)
seq1 = seq1[1:]
elif first_seq1 < first_seq2:
res.append(first_seq2)
seq2 = seq2[1:]
else:
if seq1 > seq2:
res.append(first_seq1)
seq1 = seq1[1:]
else:
res.append(first_seq2)
seq2 = seq2[1:]
return res