欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 【专题刷题】双指针(三):两数之和,三数之和,四数之和

【专题刷题】双指针(三):两数之和,三数之和,四数之和

2025/4/19 10:01:35 来源:https://blog.csdn.net/tan_run/article/details/147314143  浏览:    关键词:【专题刷题】双指针(三):两数之和,三数之和,四数之和

📝前言说明:

  • 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽

视频

  • 167. 两数之和 II
    • 个人解
    • 优质解
  • 15. 三数之和
    • 个人解
    • 优质解
  • 18. 四数之和
    • 个人解
    • 优质解


167. 两数之和 II

在这里插入图片描述

个人解

思路:
暴力求解的时间复杂度:O($n^2$)每次移动只能获取一个信息,移动 n 2 n^2 n2 次,才能得到所有两数相加的结果。

那使用双指针呢?

使用双指针,利用数组的非递减性(也就是非严格单调递增性)
我们让一个指针指向左边最小的元素,一个指针指向右边最大的元素
要寻找numbers[left] + numbers[right] == target
numbers[left] + numbers[right] > target的时候为例,让right--,移动一次得到n个信息,因为当最小数和numbers[right]相加都大于target了,那其他numbers[left]之后更大的数与numbers[right]相加就没有意义了,一下可以排除n个数。left++也同理

用时:3:00
屎山代码:

class Solution {
public:vector<int> twoSum(vector<int>& numbers, int target) {int left = 1, right = numbers.size();while(left < right){int sum = numbers[left - 1] + numbers[right - 1];if(sum < target)left++;else if(sum > target)right--;elsereturn {left, right};}return {-1,-1};}
};

时间复杂度:O(n)
空间复杂度:O(1)


优质解

简单题简单做,双指针已够用


15. 三数之和

在这里插入图片描述

个人解

思路:用base遍历整个数组,作为基准,将问题转换成nums[left] + nums[right] = 0 - nums[base]的问题。然后基于这个标准(nums[left] + nums[right] = 0 - nums[base]),再利用数组的单调性,再次用双指针。

用时:20:00(为什么这么长,因为题目要求不能重复,被去重坑惨了)
屎山代码:

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {ranges::sort(nums);int n = nums.size(), base = 0;vector<vector<int>> ans;for(; base < n - 2; base++){int left = base + 1, right = n - 1;while(left < right){if(nums[base] + nums[left] + nums[right] < 0)left++;else if(nums[base] + nums[left] + nums[right] > 0)right--;else{ans.push_back({nums[base], nums[left], nums[right]});while(left < right && nums[left + 1] == nums[left])left++;while(left < right && nums[right - 1] == nums[right])right--;left++;right--;}}while(base < n - 3 && nums[base + 1] == nums[base])base++;}return ans;}
};

时间复杂度:O( n 2 n^2 n2)
空间复杂度:O(1)


优质解

思路:双指针已经够用
但是我们来欣赏一下别人处理重复元素的思路,以及其他优化,和优雅的代码
代码(来自Leetcode上灵茶山艾府):

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {ranges::sort(nums);vector<vector<int>> ans;int n = nums.size();for (int i = 0; i < n - 2; i++) {int x = nums[i];// 跳过重复数字,base在使用前确保是唯一的,数组中无重复if (i && x == nums[i - 1]) continue; // 优化一(加上两个最小数)if (x + nums[i + 1] + nums[i + 2] > 0) break; // 优化二(加上两个最大数)if (x + nums[n - 2] + nums[n - 1] < 0) continue; int j = i + 1, k = n - 1;while (j < k) {int s = x + nums[j] + nums[k];if (s > 0) {k--;} else if (s < 0) {j++;} else { // 三数之和为 0ans.push_back({x, nums[j], nums[k]});// 跳过重复数字(用 for 可以多跳一步,直接跳到不相等的下一个元素)for (j++; j < k && nums[j] == nums[j - 1]; j++); for (k--; k > j && nums[k] == nums[k + 1]; k--);}}}return ans;}
};

18. 四数之和

个人解

在这里插入图片描述
思路:借助三数之和的解决方法,定好一个base以后又转换成三数之和的问题。
不过这时候优化的地方有两个,因为其实可以看做是有两个base
用时:19:00

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {ranges::sort(nums);vector<vector<int>> ans;int n = nums.size();for(int base = 0; base < n - 3; base++){   // 错误示范:应该要先用完再去除,因为万一其他数用的和base一样呢?// if(base < n - 4 && nums[base + 1] == nums[base])//     continue; // 去除重复元素if(base && nums[base] == nums[base - 1])continue;long long x = nums[base]; // 这题老六 数字会溢出if(x + nums[base + 1] + nums[base + 2] + nums[base + 3] > target)break;if(x + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue;for(int i = base + 1; i < n - 2; i++){if(i > base + 1 && nums[i] == nums[i - 1])continue;long long y = nums[i];if(x + y + nums[i + 1] + nums[i + 2] > target)break;if(x + y + nums[n - 2] + nums[n - 1] < target) continue;int j = i + 1, k = n - 1;while(j < k){if(x + y + nums[j] + nums[k] < target)j++;else if(x + y + nums[j] + nums[k] > target)k--;else{ans.push_back({(int)x, (int)y, nums[j], nums[k]});for(j++; j < k && nums[j] == nums[j - 1]; j++);for(k--; j < k && nums[k] == nums[k + 1]; k--);}}}}return ans;}
};

时间复杂度:O( n 3 n^3 n3)
空间复杂度:O(1)

注意跳过重复元素:必须是用完以后base再跳过重复元素,因为有可能后面的数可能取和base一样的值,但是被base跳过了就取不到了。

优质解

双指针已足以,暂时不探索其他解


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词