321.拼接最大数

90 阅读1分钟

题目:
给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。

求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。

说明: 请尽可能地优化你算法的时间和空间复杂度。
算法:
从nums1中取出最大的i个数,从nums2中取出最大的k - i个数,将这两个数拼接成一个数,取最大值。

func maxNumber(nums1 []int, nums2 []int, k int) []int {
	max := make([]int, 0)
	for i := 0; i <= k; i ++ {
		if i > len(nums1) || k - i > len(nums2) {
			continue
		}
		number1 :=  getMaxNumber(nums1, i)
		number2 :=  getMaxNumber(nums2, k - i)
		number := merge(number1, number2)
		// fmt.Println(number1,number2,number)
		if less(max, number) {
			max = number
		}
	}
	return max

}

func merge(nums1 []int, nums2 []int) []int {
    

	ans := make([]int, 0)
	for len(nums1) > 0 && len(nums2) > 0 {
		if less(nums1, nums2) {
			ans = append(ans, nums2[0])
			nums2 = nums2[1:]
		} else {
			ans = append(ans, nums1[0])
			nums1 = nums1[1:]	
		}
	}

	if 0 < len(nums1){
		ans = append(ans, nums1...)
	}

	if 0 <  len(nums2) {
		ans = append(ans, nums2...)
	}
	return ans
}

func getMaxNumber(nums []int, k int) []int {
	stack := make([]int, 0)
	length := len(nums)
	n := k
	for i := range nums {
		for length-i > n && len(stack) > 0 && stack[len(stack)-1] < nums[i] {
			stack = stack[:len(stack)-1]
			n++
		}
		stack = append(stack, nums[i])
		n--
	}
	if n < 0 {
		stack = stack[:k]
	}
	return stack
}

// 这里的less定义[1,2] > [1,2,3]
// 因为1.merge的时候需要先从nums1 nums2中较大的数组中取出。不能用归并排序的双指针,先取大的数字的方法。
// 如nums1=[6,7], nums2=[6,0,3] 按照归并排序的取数防法,可能取到[6,6,7,0,3],与要取得[6,7,6,0,3]不符合
// 2.maxNumber使用less函数时,len(nums1) == len(nums2)
func less(nums1 []int, nums2 []int) bool {
	// if len(nums1) < len(nums2)  {
	// 	return true
	// }
	i := 0
	for i < len(nums1) && i < len(nums2) {
		if nums1[i] < nums2[i] {
			return true
		} else if nums1[i] > nums2[i] {
			return false
		}
		i ++
	}
	return i < len(nums2)
}