【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 != j、i != k 且 j != 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(numsi, numsl, numsr))

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

相关推荐
糖果豆豆3 分钟前
让 AI 自查三遍,它只会把错的说得更像对的——检查的人和被检查的,是同一个
算法·架构
总裁余(余登武)2 小时前
K-means算法改进(Python版)
python·算法·kmeans
灯澜忆梦2 小时前
【面向对象编程c++】| 指针与自定义数据类型
开发语言·c++·算法
xxwl5852 小时前
区域赛算法模版第八章---贪心(Greedy)
c++·笔记·学习·算法
CCblandy3 小时前
向量检索 ANN 参数实测:换一种数据分布,recall 掉了 51 个百分点
人工智能·python·算法·自然语言处理·性能优化
CS创新实验室3 小时前
一棵树怎么做到“自平衡还不太费力“?——红黑树的旋转与染色
数据结构·算法·红黑树·408·计算机考研
Logic1013 小时前
C语言/数据结构位运算题解:异或XOR找出被挑选一次的果子编号——只出现一次的数字
c语言·数据结构·算法·数组·位运算·时间复杂度·空间复杂度
深圳市快瞳科技有限公司3 小时前
面向端侧部署的多帧宠物身份识别:完整性评分机制与工程约束
人工智能·算法·计算机视觉·端侧ai·宠物识别·宠物ai·宠物身份识别
从小白到软工5 小时前
4-3 项目-学生成绩管理系统(上)
c语言·开发语言·数据结构·经验分享·ai编程
悠仁さん5 小时前
非类型模板参数的特化与偏特化
java·数据结构·算法