原题链接:LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)
题目的意思:通过给定的数组,找出两个值,相加并等于目标值。
第一种思路,暴力枚举,伪代码如下:
for (int i = 0; i < n; ++i)
{
for (int j = i + 1; j < n; ++j)
{
if (nums[i] + nums[j] == target) break;
}
}
可以看出,时间复杂度为 O(N^2),
第二种思路: 采用双指针 + 单调性解决问题。
同时,题目有一个条件,其数据是按照升序排序的。
假设数据为 [8, 21, 27, 34, 52, 66],目标值为61;
我们先固定两个值,让这两个值相加,这两个值相加的结果无非就三种:
- left + right > target;
- left + right < target;
- left + right = target;
如果是第一种情况,因为数据是有序的,且left是当前范围 [left, right] 最小的数据,最小的数据 + right (66) 都大于了目标值 (61),因此,66 这个值就可以排除了,即 right 向左移动;
如果是第二种情况,因为此时 right 是当前范围 [left, right] 中最大的数据,最大的数据 + left 都小于目标值,因此,left 当前位置的数据就可以排除了,故 left 向右移动;
如果是第三种情况,那么说明找到了目标的两个值,返回即可。
代码如下:
class Solution {
public:
inline int Compare(int x, int y, int target)
{
return x + y - target;
}
vector<int> twoSum(vector<int>& price, int target) {
int left = 0;
int right = price.size() - 1;
while(left < right)
{
int ret = Compare(price[left],price[right],target);
if(ret > 0) right--;
else if(ret < 0) left++;
else break;
}
return {price[left], price[right]};
}
};
此时的时间复杂度就是 O(N),因为left 向右移动,right 向左移动,最坏情况也就是遍历一遍数组。
以此为基础,我们接下来讨论三数之和。 LeetCode 15. 三数之和-CSDN博客