【算法通关】双指针技巧深度解析:从基础到巅峰(Java 最优解)

【算法通关】双指针技巧深度解析:从基础到巅峰(Java 最优解)


我的主页: 寻星探路
个人专栏: 《JAVA(SE)----如此简单!!! 》 《从青铜到王者,就差这讲数据结构!!!》
《数据库那些事!!!》 《JavaEE 初阶启程记:跟我走不踩坑》
《JavaEE 进阶:从架构到落地实战 》 《测试开发漫谈》
《测开视角・力扣算法通关》 《从 0 到 1 刷力扣:算法 + 代码双提升》
《Python 全栈测试开发之路》
没有人天生就会编程,但我生来倔强!!!

寻星探路的个人简介:


在处理数组相关算法时,双指针(Two Pointers) 能够巧妙地利用区间单调性或位置关系,将原本需要 的暴力搜索优化至 。本文精选四道经典题型,附带保姆级代码注释。


一、 移动零 (Move Zeroes) ------ 快慢指针

1. 算法思路

  • 慢指针 (slow):指向"下一个非零元素应该存放的位置"。
  • 快指针 (fast):遍历数组,寻找非零元素。
  • 通过交换,非零元素被"推"到前面,零自然被"挤"到了后面。

2. Java 代码实现

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        // slow 指针之前(不含 slow)全是非零数
        int slow = 0; 
        for (int fast = 0; fast < nums.length; fast++) {
            // 当快指针发现非零数时
            if (nums[fast] != 0) {
                // 如果快慢指针不相等,说明中间有 0,需要交换
                if (fast > slow) {
                    int temp = nums[slow];
                    nums[slow] = nums[fast];
                    nums[fast] = temp;
                }
                // 无论是否交换,slow 都要后移,因为当前 slow 位置已被非零数占据
                slow++;
            }
        }
    }
}

二、 盛最多水的容器 (Container With Most Water) ------ 左右指针

1. 算法思路

  • 核心原理:木桶效应。容量由"短板"决定。
  • 指针移动逻辑:若移动长板,宽度减小,高度依然受限于短板,容量只会变小;只有移动短板,才可能换来更高的高度。

2. Java 代码实现

java 复制代码
class Solution {
    public int maxArea(int[] height) {
        int left = 0, right = height.length - 1; // 定义左右边界
        int max = 0; // 存储最大面积
        
        while (left < right) {
            // 1. 计算当前面积:宽 (right - left) * 高 (左右两端的最小值)
            int currentArea = Math.min(height[left], height[right]) * (right - left);
            
            // 2. 更新全局最大面积
            max = Math.max(max, currentArea);
            
            // 3. 贪心策略:哪边矮,就移动哪边的指针
            if (height[left] < height[right]) {
                left++; 
            } else {
                right--;
            }
        }
        return max;
    }
}

三、 三数之和 (3Sum) ------ 排序 + 左右指针

1. 算法思路

  • 排序:使数组有序,方便使用双指针并进行去重。
  • 枚举 :固定第一个数 a,在剩下的区间里通过双指针寻找 bc,使得 a + b + c = 0

2. Java 代码实现

java 复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        Arrays.sort(nums); // 1. 先排序
        int n = nums.length;
        
        for (int i = 0; i < n; i++) {
            // 如果当前数大于 0,由于数组有序,后续三个数之和一定大于 0
            if (nums[i] > 0) break; 
            
            // 2. 对第一个数 a 去重:如果当前数和前一个数相同,跳过
            if (i > 0 && nums[i] == nums[i - 1]) continue; 
            
            int left = i + 1, right = n - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum == 0) {
                    ans.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    // 3. 对第二个数 b 去重
                    while (left < right && nums[left] == nums[left + 1]) left++;
                    // 4. 对第三个数 c 去重
                    while (left < right && nums[right] == nums[right - 1]) right--;
                    
                    left++;
                    right--;
                } else if (sum < 0) {
                    left++; // 和太小,左指针右移增加数值
                } else {
                    right--; // 和太大,右指针左移减小数值
                }
            }
        }
        return ans;
    }
}

四、 接雨水 (Trapping Rain Water) ------ 双指针巅峰

1. 算法思路

  • 单点逻辑:位置 能接的水 = 。
  • 双指针优化:我们不需要预处理所有高度,只需要用两个指针从两侧向中间靠拢。

2. Java 代码实现

java 复制代码
class Solution {
    public int trap(int[] height) {
        int left = 0, right = height.length - 1;
        int leftMax = 0, rightMax = 0; // 记录左边和右边遇到的最高高度
        int res = 0;
        
        while (left < right) {
            // 更新左右两侧目前的最高墙
            leftMax = Math.max(leftMax, height[left]);
            rightMax = Math.max(rightMax, height[right]);
            
            // 如果左边的墙比右边的墙矮
            // 意味着:对于 left 这个点,接多少水取决于左侧的 leftMax(因为右侧一定有比它更高的墙)
            if (leftMax < rightMax) {
                res += (leftMax - height[left]);
                left++;
            } else {
                // 反之,right 这个点接多少水取决于右侧的 rightMax
                res += (rightMax - height[right]);
                right--;
            }
        }
        return res;
    }
}

💡 总结:双指针解题的思考模版

  1. 场景识别
  • 同向指针(快慢指针):常用于处理"原地修改"或"寻找循环/中点"。
  • 相向指针(对撞指针):常用于处理"有序数组寻找两数/多数之和"或"区间极值(盛水/接水)"。
  1. 核心三要素
  • 指针初始化 :是 (0, length-1) 还是 (0, 0)
  • 移动条件:什么情况下左移?什么情况下右移?(通常依据单调性判断)。
  • 收缩条件:如何有效跳过重复解(去重)以保证效率?

通过以上四道题的练习,你应该能感受到双指针在降低时间复杂度方面的巨大威力。


感谢你的阅读!如果觉得代码注释对你有帮助,欢迎点赞和收藏!

相关推荐
wen__xvn2 小时前
力扣第 484 场周赛
算法·leetcode·职场和发展
知识分享小能手2 小时前
Ubuntu入门学习教程,从入门到精通,Ubuntu 22.04中的人工智能—— 知识点详解 (25)
人工智能·学习·ubuntu
cyyt2 小时前
深度学习周报(1.05~1.11)
人工智能·深度学习
崇山峻岭之间2 小时前
Matlab学习记录32
开发语言·学习·matlab
向上的车轮2 小时前
如何选择Python IDE?
开发语言·ide·python
Destiny_where2 小时前
Claude VSCode插件版接入强大的GLM(无需登录注册claude code)
ide·人工智能·vscode·编辑器·claude code
小北方城市网2 小时前
微服务接口设计实战指南:高可用、易维护的接口设计原则与规范
java·大数据·运维·python·微服务·fastapi·数据库架构
小棠师姐2 小时前
零基础入门卷积运算:计算机视觉的数学基础
人工智能·计算机视觉
RockHopper20252 小时前
人类具身认知中作为“起点”的强约束机制是人工智能应用发展面临的最大挑战
人工智能·具身智能·具身认知