合并两个有序数组
题目描述
给你两个按非递减顺序排列的整数数组nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。 为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
- 示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
- 示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。 合并结果是 [1] 。
- 示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。 合并结果是 [1] 。 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
解题思路:
首先这是一道简单题,题意也很清楚,就是将两个数组合并以后,在进行排序。 其中m是num1中不需要变的数,n是num2中需要插入num1中的数。 所以第一版想的是用循环直接插(没想用sort)
func merge(nums1 []int, m int, nums2 []int, n int) {
length2 := len(nums2)-1
total := m+n
var numbers [total]int
for j :=0; j<m ; j++{
numbers[j]=nums1[j]
}
for i :=0 ; i<=length2 ; i++{
a := i + m
b := i
numbers[a]=nums2[b]
}
return numbers
}
运行后出现报错信息
`Line 4: Char 5: total declared but not used (solution.go)
Line 5: Char 18: invalid array length total (solution.go)`
查gpt解释:
您遇到的错误是因为 Go 不允许声明长度不是编译时已知的常量值的数组。在您的代码中,数组数字的长度是使用变量 Total 定义的,该变量不是常量。
要解决此问题,您可以使用切片而不是数组。 Go 中的切片更加灵活,并且允许动态调整大小。这是使用切片的代码的更新版本
很明显,因为total是个不定值,所以不能直接初始化,和c++不一样呢。
解决方法为:
total := m + n
numbers := make([]int, total)
使用make来创建所需要的空间。
更改完以后本来以为能对来着(
但是运行代码,输入[1,2,3,0,0,0] 3 [2,5,6] 3只会输出[1,2,3,0,0,0],很明显和答案不一样。
显而易见是插拼接出现了问题。
查询原因:
在提供的代码中,您可以使用 make([]int,total) 正确初始化一个名为numbers 的新切片,其具有所需的长度。然后,将 nums1 中的元素复制到前 m 个元素的数字中,这似乎是正确的。
但是,问题出在第二个循环中,您尝试将元素从 nums2 复制到数字中。问题出在行 length2 := len(nums2) - 1 上。通过从长度中减去 1,您将索引移动 1 并且错误地分配了值。
把第二个循环改成:
for i := 0; i < n; i++ {
a := i + m
numbers[a] = nums2[i]
}
最后所写的ac代码
最后提交的时候看到了要用nums1输出,悲,写复杂了。最后还是用了sort排序。注意哈,如果像我下面写的一样,注意主函数的写法。
func merge(nums1 []int, m int, nums2 []int, n int) {
for i := 0; i < n; i++ {
a := i + m
nums1[a] = nums2[i]
}
sort.Ints(nums1)
}
在您提供的代码中,函数 merge 没有显式返回任何值。在 Go 中,当函数指定了返回类型,但没有使用 return 语句时,该函数将自动返回该类型的零值。
就您的代码而言,由于合并函数的返回类型是 void 或 ()(无返回值),因此调用该函数不会向调用者提供任何值。该函数将就地修改 nums1 切片,但不会返回新切片或任何其他值。
如果在调用 merge 函数后需要访问修改后的 nums1 切片,则可以直接使用 nums1 切片变量。例如:
nums1 := []int{1, 2, 3, 0, 0, 0}
m := 3
nums2 := []int{2, 5, 6}
n := 3
merge(nums1, m, nums2, n)
// Access the modified nums1 slice
fmt.Println(nums1) // Output: [1 2 3 2 5 6]
这样属于你想输出哪个值,就print出来即可。
有返回值的写法
func merge(nums1 []int, m int, nums2 []int, n int) []int {
for i := 0; i < n; i++ {
a := i + m
nums1[a] = nums2[i]
}
return nums1
}
主函数的写法应该变成
func main() {
nums1 := []int{1, 2, 3, 0, 0, 0}
m := 3
nums2 := []int{2, 5, 6}
n := 3
merged := merge(nums1, m, nums2, n)
fmt.Println(merged)
}
很明显由于调用后返回的是nums1,所以直接赋值输出即可
另一种写法:三指针
在此更新的代码中,我使用三个指针:i 代表 nums1,j 代表 nums2,k 跟踪合并数组中的位置。我们从数组的末尾开始比较元素,将较大的元素放在 nums1 的末尾。然后我们移动相应的指针并减少 k。此过程一直持续到 nums1 或 nums2 完全合并为止。最后,如果 nums2 中还有剩余元素,则将它们复制到 nums1 的开头
代码复杂度只有m+n.
func merge(nums1 []int, m int, nums2 []int, n int) {
i := m - 1
j := n - 1
k := m + n - 1
for i >= 0 && j >= 0 {
if nums1[i] > nums2[j] {
nums1[k] = nums1[i]
i--
} else {
nums1[k] = nums2[j]
j--
}
k--
}
for j >= 0 {
nums1[k] = nums2[j]
j--
k--
}
}
我写了这两种解答以后,再去看看官方解答。
官方解答:直接合并后排序
这个算是我的第一种写法,不过直接用copy。简单很多,我不太熟悉这些操作,悲。
func merge(nums1 []int, m int, nums2 []int, _ int) {
copy(nums1[m:], nums2)
sort.Ints(nums1)
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/merge-sorted-array/solution/he-bing-liang-ge-you-xu-shu-zu-by-leetco-rrb0/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
官方解答方法二:双指针
方法一没有利用数组nums1与nums2已经被排序的性质。为了利用这一性质,我们可以使用双指针方法。这一方法将两个数组看作队列,每次从两个数组头部取出比较小的数字放到结果中。 代码如下:
func merge(nums1 []int, m int, nums2 []int, n int) {
sorted := make([]int, 0, m+n)
p1, p2 := 0, 0
for {
if p1 == m {
sorted = append(sorted, nums2[p2:]...)
break
}
if p2 == n {
sorted = append(sorted, nums1[p1:]...)
break
}
if nums1[p1] < nums2[p2] {
sorted = append(sorted, nums1[p1])
p1++
} else {
sorted = append(sorted, nums2[p2])
p2++
}
}
copy(nums1, sorted)
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/merge-sorted-array/solution/he-bing-liang-ge-you-xu-shu-zu-by-leetco-rrb0/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
他的大概思路就是,先创建一个空数组sort,然后将nums1,nums2中的数排序,最后将俩个数比较,插入小的。 其实,emmm,感觉有一说一不如三指针。