【LeetCode 手撕算法】(双指针) 1-两数之和、283-移动零、11-盛最多水的容器、15-三数之和

1-两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

复制代码
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

复制代码
输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

复制代码
输入:nums = [3,3], target = 6
输出:[0,1]

思路:本题由于不能排序,如果用双指针相当于暴力解法,先定左指针位置,右指针遍历,然后依次换左指针位置。 因为输出数字的位置,所以不能直接排序,若能排序 直接可以使用双指针。

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int l=0,r=nums.length-1;
        for(l=0;l<nums.length;l++){
            while(l<r){
                if(nums[l]+nums[r]==target){
                    return new int[]{l,r}; 
                }
                r--;
            }
            r=nums.length-1;
        }
        return new int[0];

    }
}

细节注意: 注意返回值 return new int [ ] { l,r} 为新建一个int数列,值为l,r

return new int [ 0 ] 指返回长度为0的int数列。不能直接返回 null,否则会出现NullPointerException错误


283-移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

复制代码
输入: nums =[0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

复制代码
输入: nums =[0]
输出:[0]

**思路:**使用左右指针 i 和 j ,初始都在最左端,j一直向右前进遇到0就跳过,遇到非0就与i交换值,每换一次i就向右移动一次。这样j可以遍历完使用的元素去找非0,i的位置始终是0 等j找到就交换。

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int i=0,j=0;
        while(j<nums.length){
            if(nums[j]!=0){
                int swap=nums[i];
                nums[i]=nums[j];
                nums[j]=swap;
                i++;
            }
            j++;
        }
    }
}

细节注意:

int i=0,j=0; 需要分开定义,不能是int i,j=0;

开头为void,则不需要返回值;如果为 int [ ] ,则直接返回 return nums;


11-盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

复制代码
输入:[1,8,6,2,5,4,8,3,7]
输出:49 
输入:height = [1,1]
输出:1

思路: 使用左右指针两端开始遍历,由于取面积最大(面积最大取决于最小的那个),所以需要移动最小的那个,即 左指针右移 右指针左移,直到相等结束。每移一次算一下面积,取最大值。

java 复制代码
class Solution {
    public int maxArea(int[] height) {
        int l=0,r=height.length-1;
        int max=0;
        while(l<r){
            int area=Math.min(height[l],height[r])*(r-l);
            max=Math.max(area,max);
            if(height[l]<height[r]){
                l++;
            }else{
                r--;
            }
        }
        return max;
    }
}
细节注意:

Math.min() 和 Math.max() 可以直接求最大最小。


15-三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

复制代码
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 

**思路:**先排序,由于三个数字各不相同,先定一个数nums[ i ],然后取剩下两个之和为 -nums[ i ]即可。用双指针从i之后的两端遍历就行,当l和r相等时结束。但是要注意出现重复的情况(即i会重复, l或r在移动过程中也会重复。先进行操作,在移动之后若与上一个相等,则跳过。)

java 复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums); 
        int l=0;
        List<List<Integer>> res = new ArrayList<>();

        for(int i=0;i<nums.length;i++){
            if (i > 0 && nums[i] == nums[i - 1]) continue;//跳过i重复的元素
            l=i+1;int r=nums.length-1;int target=-nums[i];
            while(l<r){
                if(nums[l]+nums[r]==target){
                    res.add(Arrays.asList(nums[i], nums[l], nums[r]));
                    l++;
                    r--;
                    // 跳过重复元素
                    while (l < r && nums[l] == nums[l - 1]) l++;
                    while (l < r && nums[r] == nums[r + 1]) r--;
                }else if(nums[l]+nums[r]>target){
                    r--;
                }else if(nums[l]+nums[r]<target){
                    l++;
                }
            }
        }
        return res;
    }
}

细节注意:

1、使用双指针必须排序Arrays.sort(xx);,才能发挥优势,两指针能比较 才能专门进行移动

2、将元素以List形式存进res列表,res.add(Arrays.asList(nums[i], nums[l], nums[r]))

3、每次执行r需要重置,再放在最右端

相关推荐
mygugu2 小时前
归纳理解epoch、batch、batch size、step、iteration深度学习名词
人工智能·算法
AI科技星2 小时前
基于双隐含量(角速度 +质量 )的全量变形公式体系-发现新公式
开发语言·人工智能·线性代数·算法·矩阵·数据挖掘
minji...2 小时前
Linux 基础IO (三) (用户缓冲区/内核缓冲区深刻理解)
java·linux·运维·服务器·c++·算法
困死,根本不会2 小时前
蓝桥杯python备赛笔记之(八)动态规划(DP)
笔记·python·学习·算法·蓝桥杯·动态规划
whycthe2 小时前
c++动态规划算法详解
c++·算法·动态规划
不想看见4043 小时前
Single Number位运算基础问题--力扣101算法题解笔记
数据结构·算法
靠沿3 小时前
【优选算法】专题十二——栈
算法
李昊哲小课3 小时前
Python 高级数据结构
开发语言·数据结构·python
无心水3 小时前
【任务调度:框架】10、2026最新!分布式任务调度选型决策树:再也不纠结选哪个
人工智能·分布式·算法·决策树·机器学习·架构·2025博客之星