双指针c++

ops/2025/2/2 1:36:52/

双指针(Two Pointers)是一种常用的算法技巧,通常用于解决数组或链表中的问题,如滑动窗口、区间合并、有序数组的两数之和等。双指针的核心思想是通过两个指针的移动来优化时间复杂度,通常可以将 (O(n^2)) 的暴力解法优化到 (O(n))。

以下是双指针的常见模板和示例:


1. 双指针的基本模板

1.1 同向双指针

  • 特点:两个指针从同一侧开始移动,通常用于滑动窗口问题。
  • 模板
    int twoPointersSameDirection(vector<int>& nums) {int left = 0, right = 0; // 初始化指针while (right < nums.size()) {// 扩展右边界right++;// 根据条件收缩左边界while (/* 不满足条件 */) {left++;}// 更新结果}return result;
    }
    

1.2 对向双指针

  • 特点:两个指针从两侧向中间移动,通常用于有序数组的问题。
  • 模板
    int twoPointersOppositeDirection(vector<int>& nums) {int left = 0, right = nums.size() - 1; // 初始化指针while (left < right) {// 根据条件移动指针if (/* 满足条件 */) {left++;} else {right--;}// 更新结果}return result;
    }
    

2. 常见应用场景

2.1 滑动窗口

  • 问题描述:找到一个满足条件的子数组或子字符串。
  • 示例:求最长无重复字符的子字符串。
    int lengthOfLongestSubstring(string s) {int left = 0, right = 0; // 滑动窗口的左右边界unordered_set<char> window; // 记录窗口内的字符int maxLen = 0;while (right < s.size()) {char c = s[right];// 如果字符已存在,移动左边界while (window.count(c)) {window.erase(s[left]);left++;}// 扩展右边界window.insert(c);right++;// 更新结果maxLen = max(maxLen, right - left);}return maxLen;
    }
    

2.2 有序数组的两数之和

  • 问题描述:在有序数组中找到两个数,使它们的和等于目标值。
  • 示例
    vector<int> 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 {left, right};} else if (sum < target) {left++;} else {right--;}}return {}; // 未找到
    }
    

2.3 区间合并

  • 问题描述:合并所有重叠的区间。
  • 示例
    vector<vector<int>> mergeIntervals(vector<vector<int>>& intervals) {if (intervals.empty()) return {};// 按区间起点排序sort(intervals.begin(), intervals.end());vector<vector<int>> merged;int left = intervals[0][0], right = intervals[0][1];for (int i = 1; i < intervals.size(); i++) {if (intervals[i][0] <= right) {// 合并区间right = max(right, intervals[i][1]);} else {// 保存当前区间merged.push_back({left, right});// 更新指针left = intervals[i][0];right = intervals[i][1];}}// 保存最后一个区间merged.push_back({left, right});return merged;
    }
    

2.4 三数之和

  • 问题描述:在数组中找到所有不重复的三元组,使它们的和等于目标值。
  • 示例
    vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(), nums.end());vector<vector<int>> result;for (int i = 0; i < nums.size(); i++) {if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重int left = i + 1, right = nums.size() - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];if (sum == 0) {result.push_back({nums[i], nums[left], nums[right]});// 去重while (left < right && nums[left] == nums[left + 1]) left++;while (left < right && nums[right] == nums[right - 1]) right--;left++;right--;} else if (sum < 0) {left++;} else {right--;}}}return result;
    }
    

2.5 链表的快慢指针

  • 问题描述:判断链表是否有环,或找到链表的中间节点。
  • 示例:判断链表是否有环。
    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;
    }
    

3. 总结

  • 同向双指针:常用于滑动窗口问题。
  • 对向双指针:常用于有序数组的问题。
  • 快慢指针:常用于链表问题。

双指针技巧的核心是通过指针的移动来减少不必要的计算,从而优化时间复杂度。


http://www.ppmy.cn/ops/154905.html

相关文章

Titans 架构下MAC变体的探究

目前业界流行的 Transformer 模型架构虽然在大多数场景表现优秀&#xff0c;但其上下文窗口&#xff08;Window&#xff09;长度的限制&#xff0c;通常仅为几千到几万个 Token&#xff0c;这使得它们在处理长文本、多轮对话或需要大规模上下文记忆的任务中&#xff0c;往往无法…

flume和kafka整合 flume和kafka为什么一起用?

‌Flume和Kafka一起使用的主要原因是为了实现高效、可靠的数据采集和实时处理。‌‌12 实时流式日志处理的需求 Flume和Kafka结合使用的主要目的是为了完成实时流式的日志处理。Flume负责数据的采集和传输,而Kafka则作为消息缓存队列,能够有效地缓冲数据,防止数据堆积或丢…

Vue.js组件开发-实现导出PDF文件可自定义添加水印及水印样式方向

使用 Vue 实现导出 PDF 文件并添加水印&#xff0c;同时支持设置水印样式、方向和自定义水印内容。 步骤 安装依赖&#xff1a;使用 html2canvas 将 HTML 内容转换为 canvas&#xff0c;使用 jspdf 生成 PDF 文件。创建 Vue 组件&#xff1a;在组件中实现水印生成、HTML 转 c…

一文介绍Hive数据类型

一文介绍Hive数据类型 文章目录 一文介绍Hive数据类型写在前面基本数据类型集合数据类型介绍案例实操 类型转化隐式类型转换CAST操作 写在前面 Linux版本&#xff1a;CentOS7.5Hive版本&#xff1a;Hive-3.1.2 基本数据类型 如下表所示&#xff1a; Hive数据类型Java数据类型…

重构字符串(767)

767. 重构字符串 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:string reorganizeString(string s){string res;//因为1 < s.length < 500 &#xff0c; uint64_t 类型足够uint16_t n s.size();if (n 0) {return res;}unordere…

“com.docker.vmnetd”将对你的电脑造成伤害。 如何解决 |Mac

电脑型号&#xff1a;Macbook pro &#xff08;Apple M3 Pro&#xff09; 系统版本&#xff1a;15.2 打开电脑突然提示“com.docker.vmnetd”将对你的电脑造成伤害&#xff0c;执行以下操作 # 停掉 Docker 服务 sudo pkill [dD]ocker# 停掉 vmnetd 服务 sudo launchctl boot…

IDEA工具下载、配置和Tomcat配置

1. IDEA工具下载、配置 1.1. IDEA工具下载 1.1.1. 下载方式一 官方地址下载 1.1.2. 下载方式二 官方地址下载&#xff1a;https://www.jetbrains.com/idea/ 1.1.3. 注册账户 官网地址&#xff1a;https://account.jetbrains.com/login 1.1.4. JetBrains官方账号注册…

cmd命令行无法进入D:盘怎么办

我找到了一个方法就是 增加一个/d cd /d d: 如下图,我不仅可以进入d盘符下&#xff0c;还可以访问盘符下的文件夹