双指针算法:高效解题的终极技巧
一、双指针核心思想双指针用两个变量模拟指针在数组 / 链表中同向或反向移动把暴力两层循环 O (n²) 优化为 O (n)无需额外开辟大量空间空间效率极高刷题最通用、上手最快的算法技巧两大核心分类左右指针首尾相向移动快慢指针同向一快一慢二、类型一左右指针相向指针适用场景有序数组、两数之和、反转数组、回文判断、区间收缩通用模板int left 0; int right nums.size() - 1; while(left right) { // 逻辑判断 if(满足条件) { left; } else { right--; } }例题 1反转数组void reverseArray(vectorint nums) { int l 0, r nums.size()-1; while(l r) { swap(nums[l],nums[r]); l; r--; } }例题 2判断回文字符串bool isPalindrome(string s) { int l 0, r s.size()-1; while(l r) { if(s[l] ! s[r]) return false; l; r--; } return true; }例题 3有序数组两数之和vectorint twoSum(vectorint nums, int target) { int l 0, r nums.size()-1; while(l r) { int sum nums[l] nums[r]; if(sum target) return {l1, r1}; else if(sum target) l; else r--; } return {}; }三、类型二快慢指针同向指针适用场景链表找中点、链表判环、数组去重、移动零、删除元素通用模板int slow 0; int fast 0; while(fast nums.size()) { // 快指针先行 if(满足条件) { nums[slow] nums[fast]; } fast; }例题 1有序数组原地去重int removeDuplicates(vectorint 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 slow1; }例题 2移动零到数组末尾void moveZeroes(vectorint nums) { int slow 0; for(int fast 0; fast nums.size(); fast) { if(nums[fast] ! 0) { swap(nums[slow],nums[fast]); slow; } } }链表快慢指针经典用法快指针走两步慢指针走一步 →找链表中间节点快慢指针相遇 →判断链表是否有环四、双指针选型口诀数组有序、首尾查找、对称判断 →左右指针数组去重、元素筛选、链表操作 →快慢指针无序数组优先哈希有序数组优先双指针五、双指针高频刷题题型汇总数组反转、字符串反转回文串校验有序数组两数 / 三数之和原地删除元素数组移动零链表找中点、链表判环盛最多水容器六、新手易错点左右指针循环条件写成leftright造成重复处理快慢指针快慢移动顺序写反无序数组强行使用左右指针导致逻辑错误原地修改数组后忘记更新有效长度七、今日总结双指针核心一左一右 / 一快一慢左右指针相向而行解决有序区间问题快慢指针同向而行完成元素筛选与原地操作绝大多数数组简单算法题优先考虑双指针优化