题目:
给定长度分别为 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)
}