一、题目:
给你两个按 非递减顺序 排列的整数数组 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 中。
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[j] <= 109
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/merge-sorted-array
二、解题思路:
从 nums1 和 nums2 的末尾开始,比较两个数组元素的大小,并将较大的元素放到 nums1 的末尾。
当其中一个数组遍历完后,将另一个数组剩余的元素按顺序填入 nums1 中。
三、考察的知识点:数组、排序、双指针
四、详细解释:
这道题目要求将两个非递减顺序排列的整数数组合并成一个非递减的整数数组。由于 nums1 是合并后的结果存储数组,我们可以利用它的额外空间来完成合并操作。首先,因为 nums1 和 nums2 都是非递减顺序排列的,所以我们可以从两个数组的末尾开始进行比较,并将较大的元素放到 nums1 的末尾。然后,我们将指针向前移动一步,继续比较直到其中一个数组遍历完。最后,如果 nums2 中还有剩余元素,我们将其按顺序填入 nums1 的前面。
双指针是一种常用的算法技巧,它使用两个指针在数据结构中同时进行移动,从而解决一些问题。我将从原理、通俗解释、应用场景、使用示例和注意事项五个方面来详细解释。
-
双指针的原理是利用两个指针分别指向不同位置的元素,并根据问题需求同时移动这两个指针。通过合理地移动指针,我们可以在线性时间内完成一些复杂的操作。
-
通俗来说,双指针就像是在数组或链表上设置了两个标记,通过这两个标记的移动,我们可以找到满足某种条件的特定元素或者进行数组中的某种操作。
-
双指针的应用场景非常广泛。它常用于解决数组和链表中的问题,比如判断回文字符串、查找和为定值的两个数、合并有序数组等。在处理有序数组时,双指针往往能够帮助我们降低时间复杂度。
下面是一个使用示例
:假设我们要在一个有序数组中寻找两个数,使得它们的和等于给定的目标值。我们可以使用双指针来实现这个功能。首先,我们将一个指针指向数组的起始位置,将另一个指针指向数组的末尾位置。然后,我们通过指针的移动来逐渐缩小寻找范围,直到找到满足条件的两个数或者确定不存在。
def find_two_sum(nums, target):
left = 0 # 左指针指向数组起始位置
right = len(nums) - 1 # 右指针指向数组末尾位置
while left < right:
current_sum = nums[left] + nums[right]
if current_sum == target: # 找到满足条件的两个数
return (nums[left], nums[right])
elif current_sum < target: # 和小于目标值,左指针右移
left += 1
else: # 和大于目标值,右指针左移
right -= 1
return None # 不存在满足条件的两个数
# 示例测试
nums = [2, 5, 7, 11, 15]
target = 9
result = find_two_sum(nums, target)
if result:
print("找到两个数的和等于目标值:", result)
else:
print("不存在满足条件的两个数")
定义了find_two_sum
函数,它接收一个有序数组nums
和目标值target
作为输入,并返回满足条件的两个数或者None
。
通过设定左指针left
和右指针right
分别指向数组的起始和末尾位置,按照指针移动的原则进行迭代。每次迭代时,我们计算当前左右指针所指向元素的和current_sum
,并与目标值target
进行比较。
如果current_sum等于target,说明找到了满足条件的两个数,直接返回它们。
如果current_sum小于target,说明和小于目标值,我们将左指针右移一位,以增加和的值。
如果current_sum大于target,说明和大于目标值,我们将右指针左移一位,以减少和的值。
通过不断地移动指针,可以逐渐缩小寻找范围,直到找到满足条件的两个数或者确定不存在。
在示例中,使用有序数组[2, 5, 7, 11, 15]和目标值9进行测试。按照双指针的原理进行迭代,最终找到了满足条件的两个数2和7,并将结果打印出来。
在使用双指针时,有几点需要注意。首先,要明确双指针的移动策略,根据具体问题来选择适当的移动方式。其次,要注意边界情况的处理,避免出现数组越界错误。此外,还需要注意指针的起始位置和结束条件的设定,以防止死循环或者错过解。
五、使用Python语言巧妙实现:
def merge(nums1, m, nums2, n):
p1 = m - 1
p2 = n - 1
p = m + n - 1
while p1 >= 0 and p2 >= 0:
if nums1[p1] > nums2[p2]:
nums1[p] = nums1[p1]
p1 -= 1
else:
nums1[p] = nums2[p2]
p2 -= 1
p -= 1
while p2 >= 0:
nums1[p] = nums2[p2]
p2 -= 1
p -= 1
六、总结收获:
通过解决这个问题,我们学习了如何利用双指针和数组的特性来合并两个有序数组。这种方法避免了使用额外空间,并以时间复杂度 O(m+n) 完成了合并操作。同时,这道题也让我们更加熟悉了Python语言中对数组的操作,如下标访问和指针移动。