剑指 Offer 57. 和为s的两个数字
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
1、题目📑
输入一个递增排序的数组和一个数字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^51 <= nums[i] <= 10^6
2、思路🧠
方法一:双指针
-
初始化: 双指针 left , right 分别指向数组
nums的左右两端 。 -
循环查找: 当双指针相遇时跳出循环;
- 若
nums[left] + nums[right] > target,则指针 right 向左移动,即执行right--; - 若
nums[left] + nums[right] < targets,则指针 ii 向右移动,即执行left++; - 若
nums[left] + nums[right] = target,返回数组new int []{nums[left], nums[right]};
- 若
-
返回空数组
new int []{}。
方法二:哈希表
看到题目想到使用两个for遍历,查找是两个相加等于target,但是时间复杂度O(N^2),时间复杂度太高,因此我们使用哈希表来解决问题以此来优化时间复杂度。哈希表每次查询的时间复杂度是O(1)的,所以直接将时间复杂度优化到O(N)。
清楚哈希表每次查询的时间复杂度是O(1),之后遍历到每个元素判断 target-nums[i] 是否存在在哈希表中
- 如果存在,则说明找到这两个元素,即
num, target - num - 如果不存在,就将当前元素加入到哈希表中,继续遍历下一个元素,直到存在为止,否则返回空数组
new int []{}
废话少说 ~~~~~ 上代码!
3、代码👨💻
第一次commit AC
class Solution {
public int[] twoSum(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right){
if(nums[left] + nums[right] > target) {
right --;
}else if(nums[left] + nums[right] < target){
left++;
}else {
return new int []{nums[left], nums[right]};
}
}
return new int []{};
}
}
时间复杂度:O(N) N为数组 nums 的长度
空间复杂度:O(1) right , left为常数空间
第二次commit AC
class Solution {
public int[] twoSum(int[] nums, int target) {
Set<Integer> set_Int = new HashSet<>();
for (int num : nums) {
if (!set_Int.contains(target - num))
set_Int.add(num);
else
return new int[]{num, target - num};
}
return new int[]{};
}
}
时间复杂度:O(N) N为数组 nums 的长度
空间复杂度:O(N)
4、总结
该题目了解哈希表的映射结构,还要清楚哈希表的查询元素的时间复杂度为 O(1) 的。双指针在一些递增、递减、有序的数组中,经常使用必须了解其结构和使用过程。
❤️来自专栏《LeetCode基础算法题》欢迎订阅❤️
厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。
对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!