题目描述:
查找总价格为目标值的两个商品
购物车内的商品价格按照升序记录于数组 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:右指针,从数组最右端开始(大数)
-
sum>target:当前两数之和过大。right 和 right 左边所有数字搭配,总和都会大于 target,所以
right--(减小大数) -
sum<target:当前两数之和过小。left 和 left 右边所有数字搭配,总和都会小于 target,所以
left++(增大小数) -
sum=target:找到答案,直接返回这两个数
-
样例推演 nums=2,7,11,15,19,21, target=30
-
left=0(2), right=5(21) → sum=23 < 30 → left++
-
left=1(7), right=5(21) → sum=28 < 30 → left++
-
left=2(11), right=5(21) → sum=32 > 30 → right--
-
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) 的时间复杂度高效解决问题;若数组无序且规模较小,暴力解法也不失为一种简单可行的选择。