算法的学习笔记—和为 S 的两个数字(牛客JZ57)

img

😀前言
在算法和数据结构中,寻找两个数字的和的问题十分常见,尤其在面试和实际开发中具有广泛的应用。今天,我们讨论一个具体的问题:在一个有序数组中找出和为给定数 SSS 的两个数,并确保如果有多对数字满足要求,返回的数字乘积最小。

🏠个人主页:尘觉主页

🥰和为 S 的两个数字

题目链接

牛客网

😀题目解析

在本题中,我们需要解决以下几个关键点:

  1. 找出数组中两个数,使它们的和等于给定的目标值 SSS。
  2. 如果存在多个满足条件的组合,返回乘积最小的那一对数字。

考虑到数组是有序的,我们可以利用双指针来高效地解决这个问题。

😃解题思路

由于数组有序,我们可以使用“双指针”方法。双指针是一种常用的算法优化技巧,可以将时间复杂度降低到 O(n)O(n)O(n)。解题步骤如下:

  1. 初始化两个指针:左指针 i 指向数组的开头,右指针 j 指向数组的末尾。

  2. 求和判断

    • 计算两个指针指向元素的和 cur = nums[i] + nums[j]
    • 如果 cur 等于目标值 S,我们找到了满足条件的两个数字,直接返回结果。
    • 如果 cur 小于 S,说明需要更大的数,左指针 i 右移以增加总和。
    • 如果 cur 大于 S,说明需要更小的数,右指针 j 左移以减小总和。
  3. 循环终止:当左指针与右指针相遇时,说明没有找到符合条件的组合,返回空结果。

这种双指针的策略能够在保持高效性的同时保证结果的正确性。以下是代码实现:

public ArrayList<Integer> FindNumbersWithSum(int[] nums, int target) {
    // 初始化左指针 i 指向数组开头,右指针 j 指向数组末尾
    int i = 0, j = nums.length - 1;

    // 循环,当左指针小于右指针时继续查找
    while (i < j) {
        // 计算当前两个指针对应元素之和
        int cur = nums[i] + nums[j];

        // 如果当前和等于目标值,则找到了符合条件的两个数
        if (cur == target) {
            // 返回包含这两个数的列表
            return new ArrayList<>(Arrays.asList(nums[i], nums[j]));
        }
        
        // 如果当前和小于目标值,说明需要更大的数,移动左指针右移
        if (cur < target) {
            i++;
        } 
        // 如果当前和大于目标值,说明需要更小的数,移动右指针左移
        else {
            j--;
        }
    }
    
    // 如果未找到符合条件的两个数,返回空列表
    return new ArrayList<>();
}

😊代码解析

1. 初始化指针

代码的第一个步骤是初始化指针 ij,分别指向数组的开头和结尾。

int i = 0, j = nums.length - 1;

2. 使用双指针进行查找

接下来进入循环。只要 i < j,我们就继续进行以下步骤:

  • 求和判断:如果 nums[i] + nums[j] 等于目标值 target,则返回结果。
  • 调整指针位置:如果当前和小于目标值,增加左指针;如果当前和大于目标值,减少右指针。
while (i < j) {
    int cur = nums[i] + nums[j];
    if (cur == target)
        return new ArrayList<>(Arrays.asList(nums[i], nums[j]));
    if (cur < target)
        i++;
    else
        j--;
}

3. 返回结果

如果找不到符合条件的两个数,返回一个空的列表。

return new ArrayList<>();

💖时间复杂度分析

因为双指针只需要遍历一次数组,所以算法的时间复杂度是 O(n)O(n)O(n),其中 nnn 是数组的长度。这是该问题的最优复杂度,比暴力求解法(时间复杂度为 O(n2)O(n^2)O(n2))高效得多。

🥳示例

以下是一个具体示例,帮助我们更好地理解代码运行过程:

int[] nums = {1, 2, 4, 7, 11, 15};
int target = 15;

假设我们使用上述数组和目标值 15

  1. 初始化指针 i = 0j = 5(指向 115)。
  2. nums[i] + nums[j] = 1 + 15 = 16,大于 15,右指针左移。
  3. 更新 j = 4(指向 11),再次计算和:1 + 11 = 12,小于 15,左指针右移。
  4. 更新 i = 1(指向 2),再次计算和:2 + 11 = 13,小于 15,左指针右移。
  5. 继续直到找到和为 15 的组合 [4, 11],返回结果。

😄总结

使用双指针解题法有效地解决了有序数组中寻找和为给定值的问题。该方法不仅提高了算法的效率,还降低了时间复杂度,是面试中的常考题型。通过该题,我们学到了如何在有序数组中使用双指针高效查找满足特定条件的数对,提升了问题解决的能力。

😁热门专栏推荐
想学习vue的可以看看这个

java基础合集

数据库合集

redis合集

nginx合集

linux合集

手写机制

微服务组件

spring_尘觉

springMVC

mybits

等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持

🤔欢迎大家加入我的社区 尘觉社区

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁
希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞

img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

尘觉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值