力扣、每日一练:合并两个有序数组

一、题目:

给你两个按 非递减顺序 排列的整数数组 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 的前面。

双指针是一种常用的算法技巧,它使用两个指针在数据结构中同时进行移动,从而解决一些问题。我将从原理、通俗解释、应用场景、使用示例和注意事项五个方面来详细解释。

  1. 双指针的原理是利用两个指针分别指向不同位置的元素,并根据问题需求同时移动这两个指针。通过合理地移动指针,我们可以在线性时间内完成一些复杂的操作。

  2. 通俗来说,双指针就像是在数组或链表上设置了两个标记,通过这两个标记的移动,我们可以找到满足某种条件的特定元素或者进行数组中的某种操作。

  3. 双指针的应用场景非常广泛。它常用于解决数组和链表中的问题,比如判断回文字符串、查找和为定值的两个数、合并有序数组等。在处理有序数组时,双指针往往能够帮助我们降低时间复杂度。

下面是一个使用示例:假设我们要在一个有序数组中寻找两个数,使得它们的和等于给定的目标值。我们可以使用双指针来实现这个功能。首先,我们将一个指针指向数组的起始位置,将另一个指针指向数组的末尾位置。然后,我们通过指针的移动来逐渐缩小寻找范围,直到找到满足条件的两个数或者确定不存在。

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语言中对数组的操作,如下标访问和指针移动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
合并两个有序数组,可以使用一个新的数组来存储合并后的结果,也可以将其中一个数组的元素插入到另一个数组中。以下是一种用Java实现的方法: ```java class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { System.arraycopy(nums2, 0, nums1, m, n); Arrays.sort(nums1); } } ``` 这个方法首先使用`System.arraycopy`函数将第二个数组`nums2`的元素复制到第一个数组`nums1`的末尾,然后再对`nums1`进行排序。这样就能得到一个有序的合并数组。 另外,我们也可以使用双指针的方法来合并两个有序数组。具体步骤如下: 1. 创建三个指针,`i`指向`nums1`的末尾,`j`指向`nums2`的末尾,`k`指向合并后的数组的末尾。 2. 当`i`和`j`都大于等于0时,比较`nums1[i]`和`nums2[j]`的大小,将较大的元素赋值给`nums1[k]`,然后将对应的指针向前移动一位。 3. 当`j`小于0时,说明`nums2`中的元素已经全部合并到`nums1`中,此时合并完成。 4. 当`i`小于0时,说明`nums1`中的元素已经全部合并到`nums2`中,此时将剩余的`nums2`中的元素依次复制到`nums1`中。 下面是用Java实现的双指针方法: ```java public class Solution { public void merge(int A[], int m, int B[], int n) { int aIndex = m - 1; int bIndex = n - 1; int abIndex = m + n - 1; while (aIndex >= 0 && bIndex >= 0) { if (A[aIndex > B[bIndex]) { A = A[aIndex--]; } else { A = B[bIndex--]; } } while (bIndex >= 0) { A = B[bIndex--]; } } } ``` 这种方法不需要额外的空间,直接在第一个数组`nums1`上进行操作,时间复杂度为O(m+n)。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [力扣合并两个有序数组(Java)](https://blog.csdn.net/qq_40378795/article/details/124663508)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [浅谈JAVA实现选择排序,插入排序,冒泡排序,以及两个有序数组合并](https://download.csdn.net/download/weixin_38647822/12750416)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Java合并两个有序的整数数组](https://blog.csdn.net/luzhensmart/article/details/109269054)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QuietNightThought

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值