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

Leetcode刷题报告2——双指针法

文章目录

    • 前言
    • [15. 三数之和](https://leetcode.cn/problems/3sum/)
      • 题干
      • 题解
      • 知识点总结
    • [42. 接雨水](https://leetcode.cn/problems/trapping-rain-water/)
      • 题干
      • 题解

前言

这部分总共是4道题,我就挑两道比较典型的题写一下博客吧。

双指针法的核心思路是通过合理的安排,减少暴力枚举的次数,争取在常数复杂度内解决问题。


15. 三数之和

题干

难度:中等

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

**注意:**答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

题解

在哈希表那一章我们写了两数之和,当时要求是a+b=target,这道题很自然就想到固定abc之一,让a+b=-c,转化为两数之和问题,这样可以在常熟复杂度内解决。但是需要去重。

这是哈希表的核心代码,不再给出输入输出部分:

class Solution {
public:std::vector<std::vector<int>> threeSum(std::vector<int>& nums) {std::sort(nums.begin(), nums.end());std::vector<std::vector<int>> ans;for (int i = 0; i < nums.size(); i++) {if (i > 0 && nums[i] == nums[i - 1]) continue; // 跳过重复的istd::unordered_set<int> seen;for (int j = i + 1; j < nums.size(); j++) {int complement = -nums[i] - nums[j];if (seen.count(complement)) {ans.push_back({ nums[i], complement, nums[j] });while (j + 1 < nums.size() && nums[j] == nums[j+1]) j++; // 跳过重复的j}seen.insert(nums[j]);}}return ans;}
};

这种方法也能通过测试,只是效率略低,问题在于find过程中,每个数仍然被扫描了多次,没有真正意义上实现常数阶复杂度。

以下是完整的双指针法,确保每个数只会被扫过一次。

class Solution {
public:std::vector<std::vector<int>> threeSum(std::vector<int>& nums) {std::vector<std::vector<int>> ans;std::sort(nums.begin(), nums.end());for (int i = 0;i < nums.size();++i) {if (i > 0 && nums[i] == nums[i - 1])continue;int k = nums.size() - 1;for (int j = i + 1;j < nums.size();++j) {if (j > i + 1 && nums[j] == nums[j - 1]) continue;while (j < k && nums[i] + nums[j] + nums[k] > 0) k--;if (k == j) break;if (nums[i] + nums[j] + nums[k] == 0) ans.push_back({ nums[i],nums[j],nums[k] });}}return ans;}
};

知识点总结

  • 双指针法和单调性紧密相关,利用排序保证单调性。
  • 再次总结哈希表stl家族:unordered_map unordered_multimap unordered_set unordered_multiset 对应键唯一/允许键重复的桶结构,还有值唯一/允许值重复的集合结构。
  • 插入哈希表方法:insert和emplace。
  • 插入顺序容器方法:insert,push_back,emplace_back。
  • 现代c++统一初始化:利用{},实现变量、函数、类、容器等等几乎所有场景的初始化。
  • 初始化列表(initializer_list):利用{},创建initializer_list模板类。几乎所有的stl都提供了利用initializer_list的构造函数。

42. 接雨水

题干

难度:困难

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

img

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[i] <= 105

题解

我的第一道困难题,其实也不是非常困难,可能因为之前在洛谷写过类似的题的缘故。之前做过一些双指针法-单调栈/单调队列的问题。直接给出代码吧。

class Solution {
public:int trap(std::vector<int>& height) {int l = 0, r = height.size() - 1, maxH = 0, sumArea = 0, blockArea = 0;for (int i : height) {maxH = std::max(maxH, i);blockArea += i;}for (int h = 1;h <= maxH;++h) {while (height[l] < h) l++;while (height[r] < h) r--;sumArea += (r - l + 1);}return sumArea - blockArea;}
};

非常简单,但是足够解决问题了,方法就是先计算总面积,再减去柱子面积,即可得到水的面积。总面积通过双指针可得。

其实没什么好说的,这道题同样有单调栈解法,不过我没有写,可以看一下洛谷的单调栈问题:P1950 长方形 - 洛谷。

另外洛谷的[P2866 USACO06NOV] Bad Hair Day S - 洛谷这道题和本题核心高度一致。

相关文章:

  • 假网关-为了节省公网IP的骚操作
  • KDD 2025 | (8月轮)时空数据(Spatial-temporal)论文总结
  • 【计算机视觉】语义分割:Mask2Former:统一分割框架的技术突破与实战指南
  • 第十一届蓝桥杯 2020 C/C++组 既约分数
  • 「Mac畅玩AIGC与多模态11」开发篇07 - 使用自定义名言插件开发智能体应用
  • 《Java高级编程:从原理到实战 - 进阶知识篇二》
  • spring源码学习之一-----spring依赖包作用分析
  • 【Machine Learning Q and AI 读书笔记】- 04 彩票假设
  • 单片机-89C51部分:12 pwm 呼吸灯 直流电机
  • 【Shell 脚本编程】详细指南:第一章 - 基础入门与最佳实践
  • 类比分析AI Agent 技术
  • Python实现简易博客系统
  • Linux 第六讲 --- 工具篇(一)yum/apt与vim
  • 一个linux系统电脑,一个windows电脑,怎么实现某一个文件夹共享
  • 部署企业网站内部导航 Team-Nav 2.0
  • MCAL学习(1)——AutoSAR
  • OpenGL-ES 学习(12) ---- GPU 系统结构
  • RAG工程-基于LangChain 实现 Advanced RAG(预检索-查询优化)(上)
  • 类和对象(拷贝构造和运算符重载)下
  • 脑机接口技术:开启人类与机器的全新交互时代
  • 街区党支部书记们亮出治理实招,解锁“善治街区二十法”
  • 屠呦呦当选美国科学院外籍院士
  • 解放日报:这是一场需要定力和实力的“科技长征”
  • 巴西外长维埃拉:国际形势日益复杂,金砖国家必须发挥核心作用
  • 运动健康|不同能力跑者,跑步前后营养补给差别这么大?
  • 卡尼领导的加拿大自由党在联邦众议院选举中获胜