当前位置: 首页 > news >正文

剑指 Offer 57. 和为s的两个数字

一、题目

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]

示例 2:

输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]

限制:

1 <= nums.length <= 10^5
1 <= nums[i] <= 10^6

二、题目分析&解题思路

2.1 从头往后遍历法

有没有人和我一样,想着从头往后遍历,例如 第一个用例
2,7,11,15
依次把每个数字 与 target - nums[i] 存到 map 里
存成这样:
2,7
7,2

例如先 存 2,7
再遍历 7 时 计算 target - 7 = 2 ,再去用 map.find(2); 找到了即可
否则继续往后遍历

代码实现:

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {map<int, int> mapTemp;for(int i = 0; i < nums.size(); i++){if(nums[i] > target){break;}int iTemp = target - nums[i];if(mapTemp.find(iTemp) == mapTemp.end()){mapTemp.insert(make_pair(nums[i], iTemp));}else{nums.resize(0);auto iter = mapTemp.find(iTemp);nums.push_back(iter->first);nums.push_back(iter->second);break;}}return nums;}
};

在这里插入图片描述
虽然过了但是可以看到,所耗时间和所额外开辟的空间都非常大,这代码还不如不写
时间复杂度:常规遍历 O(N) 加上每一次的 map.find nLog(n) ,还额外开辟了map 存储 2N的空间,太鸡肋了,完全忽略了 升序这一个特点;
因此可以考虑使用双指针法

2.2 双指针遍历法

以示例 1 的用例来看,数组是升序,左小右大,那么只需要做如下操作:
在这里插入图片描述
代码实现:

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {int left = 0;int right = nums.size() -1;while(left < right){if((nums[left] + nums[right]) > target){//说明右边的数字太大了right--;}else if((nums[left] + nums[right]) < target){//说明左边的数字太小了left++;}else{nums[0] = nums[left];nums[1] = nums[right];nums.resize(2);break;}}return nums;}
};

在这里插入图片描述
是不是立马好了一点,但是感觉还是很慢,还有没有优化的空间呢?

2.3 缩减范围+双指针法

我们继续来看 这一组用例
2 7 11 15
target = 9;
用双指针的话,其实 11 15 这两个数字完全没有必要去遍历,因为 其 已经 大于 target 了。且题目已经告知
在这里插入图片描述
说明没有负数,那么说明这一部分可以舍去,可以做一个裁剪,把范围缩小,把多余的右部分数组元素舍去,减少 双指针法的 right 区间,降低时间复杂度。

    int GetRightIndex(vector<int>& nums, int target){int left = 0;int right = nums.size()-1;while(left < right){int mid = (left + right) /2;if(nums[mid] < target){left = mid + 1;}if(nums[mid] >= target){right = mid;}}return right;}

可以看到速度有效提升
在这里插入图片描述

三、代码实现

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {int left = 0;int right = GetRightIndex(nums, target);while(left < right){if((nums[left] + nums[right]) > target){//说明右的数字太大了right--;}else if((nums[left] + nums[right]) < target){//左边的数字太小了left++;}else{nums[0] = nums[left];nums[1] = nums[right];nums.resize(2);break;}}return nums;}int GetRightIndex(vector<int>& nums, int target){int left = 0;int right = nums.size()-1;int mid = 0;while(left < right){mid = (left + right) /2;if(nums[mid] < target){left = mid + 1;}if(nums[mid] >= target){right = mid;}}return right;}
};

在这里插入图片描述

http://www.lryc.cn/news/36887.html

相关文章:

  • PDF转word在线转换方法!操作简单又高效
  • Jquery项目中使用vue.js
  • 蓝桥杯 删除字符
  • 析构函数 对象数组 对象指针
  • Vue对Axios网络请求进行封装
  • Android framework HAL(HIDL)
  • QML 模型(ListModel)
  • 你还在调戏AI,有的公司已经用ChatGPT开展业务了
  • DatenLord前沿技术分享 No.20
  • 基于vivado(语言Verilog)的FPGA学习(1)——了解viviado面板和编译过程
  • PACS(CT、CR、DR、MR、DSA、RF医院影像管理系统源码)
  • Centos7 安装Mysql8.0
  • 2023年全国最新道路运输从业人员精选真题及答案18
  • web worker的基本使用案例
  • 机器看世界
  • 18、指数移动平均——EMA
  • 用Go快速搭建IM即时通讯系统
  • 2023年江苏省职业院校技能大赛中职网络安全赛项试卷-学生组-任务书
  • 如何使用码匠连接 MariaDB
  • JavaEE简单示例——Bean的实例化
  • 1229. 日期问题
  • Java 中的浅拷贝和深拷贝
  • 【java】 java开发中 常遇到的各种难点 思路方案
  • ViewBinding 和 DataBinding的使用
  • HTML+CSS入门
  • 【Vue】vue2导出页面内容为pdf文件,自定义选中页面内容导出为pdf文件,打印选中页面内容,预览打印内容
  • 保姆级使用PyTorch训练与评估自己的Replknet网络教程
  • 1/4车、1/2车、整车悬架PID控制仿真合集
  • 媒体邀约的形式和步骤
  • Unity合批处理