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 @ 2023-03-21 19:37  zhangk1988  阅读(26)  评论(0)    收藏  举报