题目描述
给了两个数组nums1和nums2,数组内元素由0-9构成,需要从两个数组中选出k个数字,并且每个数组中值数字的相对位置不能变,怎样才能组成的值最大?
基本分析
- 能感觉到对每个数组需要维护一个递减栈,这是是两个数组的问题,怎么处理?每个数组维护一个
- 怎么能保证两个数组子序列合成的长度是k?枚举可行的k种情况
- 每个数组维护单调栈的时候,同时要保证子集能取到某个长度k1,怎么处理?还有富余长度的时候就维护递减,否则凑数
- 合并的时候需要注意什么?因为有了长度的限制,每一部分未必是递减的,这样在元素相等的时候就不能随便选了,而是要看后面。例如502,301。结果是530201,不是530102。
- 怎么实现以上需求?定义一个函数看能对后面的部分进行判断;具体地如果有不等的情况直接返回大小值,如果相等继续往后看,如果某个数组取完了,大的就是另一个,例如1111 比111大
- 怎么达到最终结果?枚举每个可行的长度分配,会得到一个结果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 |
| |
总结
- 每一个子序列的取法是单调栈的做法,但是又有了长度的约束
- 每个子序列取多长无法预计,但是可以枚举
- 合并的时候注意无序的情况,需要看后面
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现