朋友们、伙计们,我们又见面了,本专栏是关于各种算法的解析,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!
C 语 言 专 栏:C语言:从入门到精通
数据结构专栏:数据结构
个 人 主 页 :stackY、
C + + 专 栏 :C++
Linux 专 栏 :Linux
目录
1. 题目解析
2. 算法原理
3. 代码实现
4. 算法复杂度
1. 题目解析
LeetCode_LCR179.查找总价值为目标值的两个商品:
https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/
LCR179.查找总价值为目标值的两个商品
购物车内的商品价格按照升序记录于数组
price
。请在购物车中找到两个商品的价格总和刚好是target
。若存在多种情况,返回任一结果即可。示例 1:
输入:price = [3, 9, 12, 15], target = 18 输出:[3,15] 或者 [15,3]示例 2:
输入:price = [8, 21, 27, 34, 52, 66], target = 61 输出:[27,34] 或者 [34,27]提示:
1 <= price.length <= 10^5
1 <= price[i] <= 10^6
1 <= target <= 2*10^6
首先这些商品价格是有序的,按照升序排列的,将题目简单化就是在该数组中求和为target的两个数。
并且如果存在多种解任意返回一种即可。
2. 算法原理
求和为target的两个数,首先想到的是暴力枚举法:
从前往后依次固定一个值,遍历数组,找到一个值与之加起来为target。(这种方法虽然简便,但是会超出时间限制)
因此我们需要使用双指针算法 + 单调性:
因为target都已明确,所以我们设置两个下标left和right,两个下标的移动方向:left从最左边开始往右走,right从最右边开始往左边走。
因为数据是升序的,所以根据单调性,最右边的是较大的,左边的是较小的。
① 如果当right指向的值与left指向的值加起来小于target时,此时right向左移并不能起到任何作用,因为right左边都是比当前位置小的值,那么与left指向的值加起来肯定也小于target,所以需要将left向右移;
② 如果当right指向的值与left指向的值加起来大于target时,此时left向右移并不能起到任何作用,因为left的右边都是比当前位置大的值,那么与right指向的值加起来也肯定大于target,所以需要将right向左移。
③ 如果right指向的值与left指向的值加起来等于target时,就找到了正确答案。
3. 代码实现
可以创建一个vector,将最终得到的结果保存在这个vector中,然后返回即可。
class Solution { public: vector<int> twoSum(vector<int>& price, int target) { int sum = 0, left = 0, right = price.size() - 1; vector<int> v; // 双指针 + 单调性 while(left < right) { sum = price[left] + price[right]; if(sum < target) left++; // 两者之和小于target else if(sum > target) right--; // 两者之和大于target else break; // 两者之和等于target } v.push_back(price[left]); v.push_back(price[right]); return v; } };
4. 算法复杂度
最坏情况移动到最中间才可以找到: 时间复杂度O(N)
没有使用额外空间:空间复杂度O(1)
朋友们、伙计们,美好的时光总是短暂的,我们本期算法的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!