321. 拼接最大数

题目描述

给了两个数组nums1和nums2,数组内元素由0-9构成,需要从两个数组中选出k个数字,并且每个数组中值数字的相对位置不能变,怎样才能组成的值最大?

f1 单调栈

基本分析

  1. 能感觉到对每个数组需要维护一个递减栈,这是是两个数组的问题,怎么处理?每个数组维护一个
  2. 怎么能保证两个数组子序列合成的长度是k?枚举可行的k种情况
  3. 每个数组维护单调栈的时候,同时要保证子集能取到某个长度k1,怎么处理?还有富余长度的时候就维护递减,否则凑数
  4. 合并的时候需要注意什么?因为有了长度的限制,每一部分未必是递减的,这样在元素相等的时候就不能随便选了,而是要看后面。例如502,301。结果是530201,不是530102。
  5. 怎么实现以上需求?定义一个函数看能对后面的部分进行判断;具体地如果有不等的情况直接返回大小值,如果相等继续往后看,如果某个数组取完了,大的就是另一个,例如1111 比111大
  6. 怎么达到最终结果?枚举每个可行的长度分配,会得到一个结果cursub,维护这个结果的最大值就行。

代码

class Solution:
def maxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:
def getmax(nums, k):
n = len(nums)
remain = n - k
st = []
for i, ch in enumerate(nums):
while st and remain and st[-1] < ch:
st.pop()
remain -= 1
st.append(ch)
return st[:k]
def merge(nums1, nums2):
m, n = len(nums1), len(nums2)
if m == 0:
return nums2
if n == 0:
return nums1
ans = []
i, j = 0, 0
while i < m or j < n:
if compare(nums1[i:], nums2[j:]) >= 0:
ans.append(nums1[i])
i += 1
else:
ans.append(nums2[j])
j += 1
return ans
def compare(nums1, nums2):
m, n = len(nums1), len(nums2)
i, j = 0, 0
while i < m and j < n:
diff = nums1[i] - nums2[j]
if diff != 0:
return diff
i += 1
j += 1
return (m - i) - (n - j)
m, n = len(nums1), len(nums2)
mn, mx = max(0, k - n), min(m, k)
maxsub = [0] * n
for i in range(mn, mx + 1):
sub1 = getmax(nums1, i)
sub2 = getmax(nums2, k - i)
cursub = merge(sub1, sub2)
if compare(cursub, maxsub) > 0:
maxsub = cursub
return maxsub

总结

  1. 每一个子序列的取法是单调栈的做法,但是又有了长度的约束
  2. 每个子序列取多长无法预计,但是可以枚举
  3. 合并的时候注意无序的情况,需要看后面
posted @   zhangk1988  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示