题目链接:321. 拼接最大数

321. 拼接最大数

class Solution(object):
    def maxNumber(self, nums1, nums2, k):
        m, n = len(nums1), len(nums2)
        maxSubsequence = [0] * k
        start, end = max(0, k - n), min(k, m)

        for i in range(start, end + 1):
            subsequence1 = self.getMaxSubsequence(nums1, i)
            subsequence2 = self.getMaxSubsequence(nums2, k - i)
            curMaxSubsequence = self.merge(subsequence1, subsequence2)
            if self.compare(curMaxSubsequence, 0, maxSubsequence, 0) > 0:
                maxSubsequence = curMaxSubsequence
        
        return maxSubsequence

    def getMaxSubsequence(self,nums,k):
        if k == 0:
            return []
        stack = [0]*k
        stack[0] = nums[0]
        i = 1
        for j in range(1,len(nums)):
            if len(nums)-j > k-i:
                if nums[j] <= stack[i-1] and i < k:
                    stack[i] = nums[j]
                    i += 1
                elif nums[j] > stack[i-1]:
                    while i >= 1 and nums[j] > stack[i-1] and len(nums)-j > k-i:
                            stack[i-1] = nums[j]
                            i -= 1
                    i += 1
            else:
                stack[i] = nums[j]
                i += 1

        return stack

    def merge(self, subsequence1, subsequence2):
        x, y = len(subsequence1), len(subsequence2)
        if x == 0:
            return subsequence2
        if y == 0:
            return subsequence1
        
        mergeLength = x + y
        merged = list()
        index1 = index2 = 0

        for _ in range(mergeLength):
            if self.compare(subsequence1, index1, subsequence2, index2) > 0:
                merged.append(subsequence1[index1])
                index1 += 1
            else:
                merged.append(subsequence2[index2])
                index2 += 1
        return merged

    def compare(self, subsequence1, index1, subsequence2, index2):
        x, y = len(subsequence1), len(subsequence2)
        while index1 < x and index2 < y:
            difference = subsequence1[index1] - subsequence2[index2]
            if difference != 0:
                return difference
            index1 += 1
            index2 += 1
        
        return (x - index1) - (y - index2)

单调栈

    def getMaxSubsequence(self,nums,k):
        if k == 0:
            return []
        stack = [0]*k
        stack[0] = nums[0]
        i = 1
        for j in range(1,len(nums)):
            if len(nums)-j > k-i:
                if nums[j] <= stack[i-1] and i < k:
                    stack[i] = nums[j]
                    i += 1
                elif nums[j] > stack[i-1]:
                    while i >= 1 and nums[j] > stack[i-1] and len(nums)-j > k-i:
                            stack[i-1] = nums[j]
                            i -= 1
                    i += 1
            else:
                stack[i] = nums[j]
                i += 1

        return stack

这一部分的目的是按顺序找到nums数列中能组成最大数的k个元素。
我这里的逻辑是,如果k=0那就直接出空数组,不然肯定至少有一位,就先直接把第一位填进去,然后遍历nums数组进行更新。

当nums剩下的位数比stack剩下的位数更多时,意思就是我们还可以在剩下的nums里挑选最大的,这种情况下,我们也可以继续更新stack的上一位:

  • 当nums[j] 比 stack的上一位更小时,stack上一位可以保持,i继续往后所以加一位;
  • 当nums[j] 比 stack的上一位更大时,我们就需要更新上一位,而且要继续往上更新,所以这里用的应该是while而不是if,进入while之后我们也需要保证nums剩下的位数比stack剩下的位数更多,不然最后会导致填不满stack,以及i是在索引范围内的。
  • 出了while之后,因为stack现在所在的那一位被填上了,所以i也需要往后一位。

一直遍历到当nums剩下的位数比stack剩下的位数相同时,意思就是我们可以不用再比较大小了,后面所有的都可以一起填进去了,再作比较就会导致位数不满。

nums = [8,7,3,6,8] k = 2
stack = [0,0]
stack = [8,0] i =1 j = 1
stack = [8,7] i =2 j = 2
stack = [8,7] i =2 j = 3, 3不更新
stack = [8,7] i =2 j = 4, 6不更新
stack = [8,8] i =2 j = 4, 8更新

比较大小

    def compare(self, subsequence1, index1, subsequence2, index2):
        x, y = len(subsequence1), len(subsequence2)
        while index1 < x and index2 < y:
            difference = subsequence1[index1] - subsequence2[index2]
            if difference != 0:
                return difference
            index1 += 1
            index2 += 1
        
        return (x - index1) - (y - index2)

进while循环,在不出范围的情况下,比较当前位置的大小,如果不一样的话,就可以直接出去了,如果一样就比较下一位,如果一直到其中一个数列走完索引了,还是一样的,就看另一位是否还有剩余。

合并为最大数

    def merge(self, subsequence1, subsequence2):
        x, y = len(subsequence1), len(subsequence2)
        if x == 0:
            return subsequence2
        if y == 0:
            return subsequence1
        
        mergeLength = x + y
        merged = list()
        index1 = index2 = 0

        for _ in range(mergeLength):
            if self.compare(subsequence1, index1, subsequence2, index2) > 0:
                merged.append(subsequence1[index1])
                index1 += 1
            else:
                merged.append(subsequence2[index2])
                index2 += 1
        return merged

这里的逻辑很简单就是 nums1现在的位置更大就先出nums1,nums2 现在的位置更大就先出nums2,一样的情况在比较大小那里已经解决了。

主代码

class Solution(object):
    def maxNumber(self, nums1, nums2, k):
        m, n = len(nums1), len(nums2)
        maxSubsequence = [0] * k
        start, end = max(0, k - n), min(k, m)

        for i in range(start, end + 1):
            subsequence1 = self.getMaxSubsequence(nums1, i)
            subsequence2 = self.getMaxSubsequence(nums2, k - i)
            curMaxSubsequence = self.merge(subsequence1, subsequence2)
            if self.compare(curMaxSubsequence, 0, maxSubsequence, 0) > 0:
                maxSubsequence = curMaxSubsequence
        
        return maxSubsequence

首先最后一次比较大小,大家的位数肯定是一样的,都是k位,那就可以一位一位的比较了,所以用上面那个比较大小的函数就可以。

07-18 21:00