ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

每日算法精讲 Day 3(双指针基础) | 移动零 复写零 与 LeetCode 202. 快乐数 与 LeetCode 11.盛最多水的容器 与 LeetCode 611 有效三角形的个数

每日算法精讲 Day 3(双指针基础) | 移动零 复写零 与 LeetCode 202. 快乐数 与 LeetCode 11.盛最多水的容器 与 LeetCode 611 有效三角形的个数 目录引言283. 移动零题目分析逻辑梳理快排分区思想代码实现复杂度分析1089. 复写零题目分析逻辑梳理代码实现复杂度分析202. 快乐数题目分析逻辑梳理快慢指针判环代码实现复杂度分析11. 盛最多水的容器题目分析逻辑梳理对向双指针代码实现复杂度分析611. 有效三角形的个数题目分析逻辑梳理排序 双向指针代码实现复杂度分析结语引言双指针是算法面试中最常用、最高效的技巧之一。它通过维护两个指针的相对位置将暴力 O(n²) 的解法优化到 O(n)且通常只需 O(1) 的额外空间。本文精选 5 道 LeetCode 经典题目从数组操作到数学规律带你掌握双指针的核心思想。接下来进入正文————283. 移动零题目分析将数组中的所有 0 移动到末尾同时保持非零元素的相对顺序不变。逻辑梳理快排分区思想维护两个指针l和rl左侧全部为非零元素l到r之间全部为0r右侧待处理区域当r遍历完数组时所有 0 自然被挤到了右侧。代码实现class Solution { public: void moveZeroes(vectorint nums) { int l -1,r 0; while(rnums.size()) { if(nums[r]) swap(nums[l],nums[r]); else r; } } };复杂度分析时间复杂度O(N)空间复杂度O(1)1089. 复写零题目分析遍历数组遇到 0 就复写一次后续元素整体右移一位。要求原地修改。逻辑梳理如果从前往后复写0 会占两个位置导致后续未处理的元素被覆盖。因此采用从后往前的策略第一步先找到最后一个被复写的数的位置第二步从后向前进行复写操作代码实现AC码class Solution { public: void duplicateZeros(vectorint arr) { int cur 0, dest -1; while (dest (int)arr.size()) { if (arr[cur]) dest; else dest 2; if (dest arr.size() - 1) break; cur; } if (dest arr.size()) { arr[dest - 1] arr[cur]; dest - 2; cur--; } while (cur0) { if (arr[cur] 0) arr[dest--] arr[cur]; arr[dest--] arr[cur--]; } } };复杂度分析时间复杂度O(N)空间复杂度O(1)202. 快乐数题目分析判断一个数字是否快乐 repeatedly 替换为各位数字的平方和最终能否得到 1。逻辑梳理快慢指针判环将每次运算后的结果视为链表中的节点如果最终能得到 1会进入1 → 1 → 1...的循环如果不能得到 1会进入其他循环使用快慢指针慢指针每次走一步快指针每次走两步。若相遇时值为 1则是快乐数否则不是。代码实现AC码class Solution { public: int func1(int k) { int ans 0; while(k) { ans pow(k%10,2); k/10; } return ans; } bool isHappy(int n) { int slow n; int fast func1(n); while(slow!fast) { slow func1(slow); fast func1(func1(fast)); } if(fast1) return true; else return false; } };复杂度分析时间复杂度O(N)空间复杂度O(1)11. 盛最多水的容器题目分析给定 n 条垂线找出两条线使得与 x 轴构成的容器能盛最多的水。面积 两线距离 × 较短线的高度。逻辑梳理对向双指针left从最左端开始right从最右端开始此时宽度最大每次移动高度较小的指针向中间靠拢原理宽度在减小只有可能通过增加高度来获得更大面积代码实现class Solution { public: int maxArea(vectorint height) { int left 0,right height.size()-1; int ans min(height[left],height[right])*(right-left); while(left!right) { if(height[left]height[right]) left; else right--; ans max(ans,min(height[left],height[right])*(right-left)); } return ans; } };复杂度分析时间复杂度O(N)空间复杂度O(1)611. 有效三角形的个数题目分析给定数组统计能组成三角形的三元组个数下标不同即可。逻辑梳理排序 双向指针三角形判定两边之和大于第三边。先排序然后固定最长边nums[i]用双指针找另外两边left 0,right i - 1若nums[left] nums[right] nums[i]则[left, right-1]所有元素与right组合都满足累加right - left然后right--否则left代码实现class Solution { public: int triangleNumber(vectorint nums) { sort(nums.begin(),nums.end()); int ans 0; for(int i 2;inums.size();i) { int left 0,right i-1; while(leftright) { if(nums[left]nums[right]nums[i]) left; else { ans right-left; right--; } } } return ans; } };复杂度分析时间复杂度O(N²)空间复杂度O(1)结语双指针的精髓在于利用有序性或单调性将枚举转化为移动。无论是同向指针维护窗口、对向指针收缩范围还是快慢指针检测循环核心都是减少不必要的重复计算。掌握这些经典模型面试中的数组问题将迎刃而解。希望以上内容对你有所帮助感谢观看若觉得写的还可以可以分享给朋友一起来看哦毕竟一起进步更有动力嘛当然能关注一下就更好啦。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进