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

【C++ 双指针技巧】

文章目录

  • 一、什么是双指针?
  • 二、使用场景
    • 1. 删除数组中重复的元素(快慢指针)
      • ✅说明:
    • 2. 判断有序数组中是否存在两个数之和为 target(对撞指针)
      • ✅说明:
    • 3. 反转字符串(对撞指针)
      • ✅说明:
    • 4. 判断链表是否有环(快慢指针)
      • ✅说明:
    • 5. 盛最多水的容器(对撞指针)
      • ✅说明:
  • 三、双指针与暴力法的对比优势


一、什么是双指针?

双指针,顾名思义就是使用两个指针(或索引)来遍历数据结构,它可以分为两类:

  • 对撞指针(Two Pointers from Both Ends):两个指针从序列的两端向中间移动。
  • 快慢指针(Fast and Slow Pointers):两个指针从一端出发,以不同的速度移动。

这种技巧可以有效地降低时间复杂度,提升算法效率。


二、使用场景

1. 删除数组中重复的元素(快慢指针)

问题描述:给定一个有序数组 nums,原地删除重复出现的元素,使每个元素只出现一次,返回新数组的长度。

#include <iostream>
#include <vector>
using namespace std;int removeDuplicates(vector<int>& nums) {if (nums.empty()) return 0;int slow = 0;for (int fast = 1; fast < nums.size(); fast++) {if (nums[fast] != nums[slow]) {slow++;nums[slow] = nums[fast];}}return slow + 1;
}int main() {vector<int> nums = {1, 1, 2, 2, 3};int len = removeDuplicates(nums);cout << "去重后长度: " << len << endl;for (int i = 0; i < len; ++i)cout << nums[i] << " ";return 0;
}

✅说明:

  • fast 快指针向前扫描;
  • slow 慢指针维护已去重序列的尾部。

2. 判断有序数组中是否存在两个数之和为 target(对撞指针)

问题描述:给定一个升序数组 nums 和一个整数 target,判断数组中是否存在两个数的和等于 target

#include <iostream>
#include <vector>
using namespace std;bool twoSum(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left < right) {int sum = nums[left] + nums[right];if (sum == target) return true;else if (sum < target) left++;else right--;}return false;
}int main() {vector<int> nums = {1, 2, 4, 7, 11, 15};int target = 15;cout << (twoSum(nums, target) ? "存在" : "不存在") << endl;return 0;
}

✅说明:

  • leftright 从两端出发,寻找匹配组合;
  • 特别适用于有序数组

3. 反转字符串(对撞指针)

问题描述:将字符串原地反转。

#include <iostream>
#include <vector>
using namespace std;void reverseString(vector<char>& s) {int left = 0, right = s.size() - 1;while (left < right) {swap(s[left++], s[right--]);}
}int main() {vector<char> s = {'h', 'e', 'l', 'l', 'o'};reverseString(s);for (char c : s) cout << c;return 0;
}

✅说明:

  • swap 的使用要特别注意 ++-- 的顺序;
  • 通常在需要原地修改结构时非常实用。

4. 判断链表是否有环(快慢指针)

问题描述:给定一个链表,判断链表中是否有环。

#include <iostream>
using namespace std;struct ListNode {int val;ListNode* next;ListNode(int x): val(x), next(nullptr) {}
};bool hasCycle(ListNode* head) {if (!head || !head->next) return false;ListNode* slow = head;ListNode* fast = head->next;while (fast && fast->next) {if (slow == fast) return true;slow = slow->next;fast = fast->next->next;}return false;
}

✅说明:

  • fast 一次走两步,slow 一次走一步;
  • 若存在环,快慢指针终将相遇。

5. 盛最多水的容器(对撞指针)

问题描述:给定一个数组 height[] 表示每个柱子的高度,找到两个柱子之间能容纳的最大水量。

#include <iostream>
#include <vector>
using namespace std;int maxArea(vector<int>& height) {int left = 0, right = height.size() - 1;int maxWater = 0;while (left < right) {int h = min(height[left], height[right]);maxWater = max(maxWater, h * (right - left));if (height[left] < height[right]) left++;else right--;}return maxWater;
}int main() {vector<int> height = {1,8,6,2,5,4,8,3,7};cout << "最大容量: " << maxArea(height) << endl;return 0;
}

✅说明:

  • 双指针在左右两端向中间靠拢;
  • 每次根据高度判断该移动哪一侧。

三、双指针与暴力法的对比优势

方法时间复杂度适用情况
暴力法O(n²)无序数组,无法优化
双指针法O(n) 或 O(nlogn)有序结构、可跳跃遍历

在查找两个数之和的情况下,暴力法需要两层循环,而双指针只需一次遍历。


文章转载自:

http://ydHBZmm8.trtdg.cn
http://S988Zda0.trtdg.cn
http://S5beIw5x.trtdg.cn
http://DVLgITRV.trtdg.cn
http://lHeoYItf.trtdg.cn
http://58UrF1Q9.trtdg.cn
http://HPoY0WH5.trtdg.cn
http://5DiJ3Nvt.trtdg.cn
http://fOOHg6ci.trtdg.cn
http://Gj6W3g04.trtdg.cn
http://k1cFq1V8.trtdg.cn
http://yQMG4ss9.trtdg.cn
http://KUzg0kCO.trtdg.cn
http://j8hFlI01.trtdg.cn
http://yQUxfysN.trtdg.cn
http://geCbjFaB.trtdg.cn
http://ZQF6B9nv.trtdg.cn
http://qp0urG6s.trtdg.cn
http://8XgqtzAg.trtdg.cn
http://DCrNzPwT.trtdg.cn
http://8To2XNl0.trtdg.cn
http://htdYmGts.trtdg.cn
http://6QR4I2Mz.trtdg.cn
http://2CL6m5S1.trtdg.cn
http://dJeoYk4o.trtdg.cn
http://zserG3HB.trtdg.cn
http://tKBM0uOS.trtdg.cn
http://jBUIuZRk.trtdg.cn
http://ouDYLJYF.trtdg.cn
http://G6njr0cT.trtdg.cn
http://www.dtcms.com/a/371020.html

相关文章:

  • Leetcode77:组合问题
  • Java多线程学习笔记
  • 命令行工具集 CDO 功能总结
  • ​抢占AI搜索新入口:2025年五大专业GEO优化服务商解析
  • 使用Ansible自动化部署Hadoop集群(含源码)--环境准备
  • FlashAttention:突破Transformer内存瓶颈的IO感知革命
  • C++ 并发编程指南 实现无锁队列
  • 制衣跟单高效管理软件推荐
  • lesson55:CSS导航组件全攻略:从基础导航条到动态三级菜单与伸缩菜单实现
  • Typora处理markdown文件【给.md文档加水印】
  • MySQL 视图全方位解析
  • 基于SVN搭建企业内部知识库系统实践
  • 编排与存储
  • Ai8051 2.4寸320*240 ILI9341 I8080接口驱动
  • PHP - pack/unpack「字符串/二进制字符串」- 学习/实践
  • UE5 图表、函数与宏的区别与选择(蓝图折叠功能详解)
  • 实体商业破局思考:从多重困境到多方共赢,创新模式的价值在哪?
  • 中州养老项目:利用Redis解决权限接口响应慢的问题
  • 轻量应用服务器具体指的是什么?
  • 3.进程调度:常见算法
  • LeetCode - 202. 快乐数
  • Docker容器安全最佳实践:镜像扫描、权限控制与逃逸防范
  • 【攻防实战】浅谈Cobalt Strike远控实战
  • 优化MySQL分区表备份流程详解
  • 《论文阅读》贴纸对多模态聊天情感分析和意图识别的影响:一个新的任务、数据集和基线 ACM MM 2025
  • 主数据系统是否对于企业是必需的?
  • 深入理解 RequestContextHolder、ThreadLocal 与 RequestContextFilter
  • GD32入门到就业37--文件系统于FatFs
  • 从零到一构建企业级AI向量服务:AntSK-PyApi深度技术解析
  • 昇腾310i Pro固件说明