《上篇:左右冲锋突击队 —— 对撞双指针手撕有序数组》 📅 2026/7/13 20:52:31 核心思想左指针left从数组最左端右指针right从数组最右端两个指针向中间靠拢收缩仅适用于有序 / 存在单调关系的序列时间复杂度 O (n)原地操作空间 O (1)。 通用模板cpp运行int left 0, right nums.size() - 1; while(left right) // 指针重合停止避免同一个元素重复使用 { // 判断条件移动对应指针 }例题 1LeetCode 167 两数之和 II - 输入有序数组题意给定升序排列数组找出两个数相加等于target返回下标从 1 开始计数保证唯一解。完整代码cpp运行#include vector using namespace std; class Solution { public: vectorint twoSum(vectorint numbers, int target) { // 初始化左右指针 int left 0; int right numbers.size() - 1; while(left right) { int sum numbers[left] numbers[right]; if(sum target) { // 题目要求下标从1开始1 return {left 1, right 1}; } else if(sum target) { // 和偏小需要增大数值左指针右移 left; } else { // 和偏大需要减小数值右指针左移 right--; } } return {}; // 题目保证有解此处不会执行 } };逐行解读left0指向最小元素right末尾指向最大元素循环条件leftright防止左右指针指向同一个元素题目要求两个不同元素求和分三种分支利用数组升序单调性单向移动指针无回溯返回下标必须 1匹配题目 1-based 格式。易错点循环条件写成left right允许同一元素自加出现非法解返回{left, right}忘记 1下标格式错误判题 WA无序数组强行使用相向指针单调性消失区间收缩逻辑失效。例题 2LeetCode 11 盛最多水的容器题意数组代表柱子高度两根柱子和 x 轴围成容器求可容纳的最大水量。完整代码cpp运行#include vector #include algorithm using namespace std; class Solution { public: int maxArea(vectorint height) { int left 0; int right height.size() - 1; int max_water 0; // 记录最大容积 while(left right) { int width right - left; int h min(height[left], height[right]); int cur width * h; max_water max(max_water, cur); // 移动更矮的柱子 if(height[left] height[right]) left; else right--; } return max_water; } };逐行解读容器宽度 左右指针距离有效高度由更短柱子决定每次计算容积并更新全局最大值移动矮侧指针矮柱是容积限制移动高柱只会缩小宽度容积不可能变大易错点移动更高一侧指针区间宽度缩小高度不变结果只会更小逻辑完全错误初始max_water-1空数组场景返回负数未引入algorithmmin/max编译报错。例题 3LeetCode 344 反转字符串题意字符数组原地反转不能开辟额外数组空间复杂度 O (1)。完整代码cpp运行#include vector using namespace std; class Solution { public: void reverseString(vectorchar s) { int l 0; int r s.size() - 1; while(l r) { swap(s[l], s[r]); // 交换两端字符 l; r--; } } };逐行解读左右指针交换对应位置字符交换完成后两个指针同时向中间移动偶数长度全部字符完成交换奇数长度最中间字符无需操作循环终止。易错点循环条件l r中间元素自己和自己交换无报错但产生无效运算交换后只移动单个指针指针不会相遇死循环。例题 4LeetCode 125 验证回文串题意仅保留字母和数字忽略大小写判断字符串是否为回文。完整代码cpp运行#include string #include cctype using namespace std; class Solution { public: bool isPalindrome(string s) { int l 0; int r s.size() - 1; while(l r) { // 左指针跳过非字母数字必须加lr防止越界 while(l r !isalnum(s[l])) l; // 右指针跳过非字母数字 while(l r !isalnum(s[r])) r--; // 统一转小写对比 if(tolower(s[l]) ! tolower(s[r])) return false; l; r--; } return true; } };逐行解读内层循环过滤空格、符号等无效字符过滤时持续约束lr有效字符统一转为小写再对比不相等直接判定不是回文匹配成功后双指针同步收缩直到相遇。易错点内层过滤循环缺少lr指针交叉后访问s[l]/s[r]数组越界程序崩溃未使用tolower大写、小写 ASCII 码不同误判非回文先移动指针再校验字符漏掉当前有效字符的对比。谢谢