【C++算法】和为s的两个数

题目描述:

查找总价格为目标值的两个商品

购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。

算法原理:

暴力解法:

两层for循环

暴力解法代码:

java 复制代码
public int[] twoSum(int[] price, int target) 
{
    int n = price.length;
    for (int i = 0; i < n; i++) 
{
        for (int j = i + 1; j < n; j++) 
        {
            if (price[i] + price[j] == target) 
            {
                return new int[]{price[i], price[j]};
            }
        }
}
    return new int[0];
}

利用单调性,使用双指针算法解决问题

cpp 复制代码
class Solution {
public:
    vector<int> twoSum(vector<int>& price, int t) 
    {
       int left =0;
       int right =price.size() -1;
       while(left<right)
       {
        if(price[left]+price[right]>t)  right--;
        else if(price[left]+price[right]<t) left++;
        else if (price[left]+price[right] == t)
        {
            return {price[right],price[left]};
        }
       }
       //照顾编译器当找不到返回值的时候返回一个数字
       return {-1,-1};
    }
};

边界条件说明:

  • 数组为空或只有一个元素 :此时无法凑出两个不同的商品,双指针循环不会进入(left 不小于 right),函数直接返回 {-1,-1},表示未找到满足条件的两个商品。
  • 找不到满足条件的两个商品 :当左右指针相遇(left 不小于 right)仍未找到和为 target 的组合时,循环结束,返回 {-1,-1} 作为兜底结果。
  • target 小于最小两数之和 :此时 priceleft + priceright 始终大于 target,右指针会不断左移(right--),直到 left 与 right 相遇,最终返回 {-1,-1}
  • target 大于最大两数之和 :此时 priceleft + priceright 始终小于 target,左指针会不断右移(left++),直到 left 与 right 相遇,最终返回 {-1,-1}

两种解法对比:

对比维度 暴力解法 双指针解法
核心思路 两层 for 循环枚举所有两数组合,逐一判断和是否为 target 利用数组升序的单调性,左右指针相向移动,逐步逼近 target
时间复杂度 O(n²) O(n)
空间复杂度 O(1) O(1)
适用场景 数组无序或数据量较小,代码直观、易于理解 数组升序有序,数据量较大时效率更高

示例数组:[2,7,11,15,19,21]target = 30

前提:数组升序有序

  • left:左指针,从数组最左端开始(小数)
  • right:右指针,从数组最右端开始(大数)
  1. sum>target:当前两数之和过大。right 和 right 左边所有数字搭配,总和都会大于 target,所以right--(减小大数)

  2. sum<target:当前两数之和过小。left 和 left 右边所有数字搭配,总和都会小于 target,所以left++(增大小数)

  3. sum=target:找到答案,直接返回这两个数

  4. 样例推演 nums=2,7,11,15,19,21, target=30

  5. left=0(2), right=5(21) → sum=23 < 30 → left++

  6. left=1(7), right=5(21) → sum=28 < 30 → left++

  7. left=2(11), right=5(21) → sum=32 > 30 → right--

  8. left=2(11), right=4(19) → sum=30 == target ✔,返回 11,19

总结

暴力解法通过两层 for 循环枚举所有两数组合,思路直观、代码简单,适合数组无序或数据量较小的场景;缺点是时间复杂度为 O(n²),当数据规模较大时性能明显下降。

双指针解法利用数组升序的单调性,让左右指针相向移动,只需一次遍历即可找到答案,时间复杂度为 O(n),空间复杂度为 O(1),在有序数组中具有显著的高效性,是处理此类问题的首选方案。

两种解法的完整复杂度对比如下:

对比维度 暴力解法 双指针解法
核心思路 两层 for 循环枚举所有两数组合,逐一判断和是否为 target 利用数组升序的单调性,左右指针相向移动,逐步逼近 target
时间复杂度 O(n²) O(n)
空间复杂度 O(1) O(1)
适用场景 数组无序或数据量较小,代码直观、易于理解 数组升序有序,数据量较大时效率更高
优点 实现简单,无需依赖数组有序性 线性时间完成查找,性能优异
缺点 双重循环导致时间开销大 要求数组必须升序有序

综上,当题目给定有序数组时,应优先采用双指针解法,以 O(n) 的时间复杂度高效解决问题;若数组无序且规模较小,暴力解法也不失为一种简单可行的选择。

相关推荐
IvanCodes6 小时前
Python 数据处理(十三):JSON、CSV 与数据序列化
开发语言·python
aramae7 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
荆棘鸟智能8 小时前
城市感知设备怎么统一接入?从多协议网关到设备模型的中间件架构设计
人工智能·算法·边缘计算
淡海水9 小时前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
Logic1019 小时前
C语言/数据结构位运算题解:异或XOR找出时尚聚会中的“独特颜色“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
qq_25183645710 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
郑州光合科技余经理11 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
知识分享小能手11 小时前
C++ 学习教程,从入门到精通,C++ 入门知识 — 完整知识点(1)
开发语言·c++·学习
qq_1998868711 小时前
第8板块·第2节:统一内存的高级特性与性能调优
c++·人工智能·gpu算力·cuda