• 算法之双指针题型:


    双指针例题小总结:

    力扣27: 移除元素

    力扣题目链接

    双指针分为:

    快慢双指针:同一个起点,同向出发

    相向双指针:从两端出发,方向相反,终会相遇

    经典的双指针(快慢双指针) 代码随想录上面有动图,很清楚

     题目:
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    思路:

    27.移除元素-双指针法

    class Solution {
        public int removeElement(int[] nums, int val) {
            // 快慢指针
            int slowIndex = 0;
            for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
                if (nums[fastIndex] != val) {
                    nums[slowIndex] = nums[fastIndex];
                    slowIndex++;
                }
            }
            return slowIndex;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    力扣977: 有序数组的平方

    力扣题目链接

     题目:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    
    示例 1:
    
    输入:nums = [-4,-1,0,3,10]
    输出:[0,1,9,16,100]
    解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
    示例 2:
    
    输入:nums = [-7,-3,2,3,11]
    输出:[4,9,9,49,121]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    也是双指针法(相向指针)

    如动画所示:

    img

    思路:数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    
    此时可以考虑双指针法了,i指向起始位置,j指向终止位置。
    
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    
    如果A[i] * A[i] < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    
    如果A[i] * A[i] >= A[j] * A[j] 那么result[k--] = A[i] * A[i]; 。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    class Solution {
        public int[] sortedSquares(int[] nums) {
            int right = nums.length - 1;
            int left = 0;
            int[] result = new int[nums.length];
            int index = result.length - 1;
            while (left <= right) {
                if (nums[left] * nums[left] > nums[right] * nums[right]) {
                    // 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置
                    result[index--] = nums[left] * nums[left];
                    ++left;
                } else {
                    result[index--] = nums[right] * nums[right];
                    --right;
                }
            }
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    力扣209:长度最小的子数组

    力扣题目链接

    题目:给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
    
    示例:
    
    输入:s = 7, nums = [2,3,1,2,4,3]
    输出:2
    解释:子数组 [4,3] 是该条件下的长度最小的子数组。
    提示:
    
    1 <= target <= 10^9
    1 <= nums.length <= 10^5
    1 <= nums[i] <= 10^5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    思路:滑动窗口 实质还是双指针(快慢指针)。

    209.长度最小的子数组

    class Solution {
    
        // 滑动窗口
        public int minSubArrayLen(int s, int[] nums) {
            int left = 0;
            int sum = 0;
            int result = Integer.MAX_VALUE;
            for (int right = 0; right < nums.length; right++) {
                sum += nums[right];
                while (sum >= s) {
                    result = Math.min(result, right - left + 1);
                    sum -= nums[left++];
                }
            }
            return result == Integer.MAX_VALUE ? 0 : result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    力扣15:三数之和

    力扣题目链接(opens new window)

    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

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

    示例:

    给定数组 nums = [-1, 0, 1, 2, -1, -4],

    满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]

    思路:这道题使用双指针做,

    代码:

    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> result = new ArrayList<>();
            Arrays.sort(nums);
    	// 找出a + b + c = 0
            // a = nums[i], b = nums[left], c = nums[right]
            for (int i = 0; i < nums.length; i++) {
    	    // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
                if (nums[i] > 0) { 
                    return result;
                }
    
                if (i > 0 && nums[i] == nums[i - 1]) {  // 去重a
                    continue;
                }
    
                int left = i + 1;
                int right = nums.length - 1;
                while (right > left) {
                    int sum = nums[i] + nums[left] + nums[right];
                    if (sum > 0) {
                        right--;
                    } else if (sum < 0) {
                        left++;
                    } else {
                        result.add(Arrays.asList(nums[i], nums[left], nums[right]));
    		    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                        while (right > left && nums[right] == nums[right - 1]) right--;
                        while (right > left && nums[left] == nums[left + 1]) left++;
                        
                        right--; 
                        left++;
                    }
                }
            }
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    力扣18:四数之和

    力扣题目链接(opens new window)

    题意:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

    注意:

    答案中不可以包含重复的四元组。

    示例: 给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]

    思路:这道题也是双指针

    代码:

    class Solution {
        public List<List<Integer>> fourSum(int[] nums, int target) {
            List<List<Integer>> result = new ArrayList<>();
            Arrays.sort(nums);
           
            for (int i = 0; i < nums.length; i++) {
    		
                // nums[i] > target 直接返回, 剪枝操作
                if (nums[i] > 0 && nums[i] > target) {
                    return result;
                }
    		
                if (i > 0 && nums[i - 1] == nums[i]) {    // 对nums[i]去重
                    continue;
                }
                
                for (int j = i + 1; j < nums.length; j++) {
    
                    if (j > i + 1 && nums[j - 1] == nums[j]) {  // 对nums[j]去重
                        continue;
                    }
    
                    int left = j + 1;
                    int right = nums.length - 1;
                    while (right > left) {
    		    // nums[k] + nums[i] + nums[left] + nums[right] > target int会溢出
                        long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
                        if (sum > target) {
                            right--;
                        } else if (sum < target) {
                            left++;
                        } else {
                            result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                            // 对nums[left]和nums[right]去重
                            while (right > left && nums[right] == nums[right - 1]) right--;
                            while (right > left && nums[left] == nums[left + 1]) left++;
    
                            left++;
                            right--;
                        }
                    }
                }
            }
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

  • 相关阅读:
    java算法收藏
    Jpa使用Specification分页查询
    【论文笔记】图神经网络采样相关工作整理9.19
    Apache Pulsar 从入门到精通
    Spring Beans 官方文档翻译笔记
    git小组分工写产品的增删改査,回顾ssm的使用
    数据分析入门,深入浅出的数据分析
    数据分析面试重点
    手把手教你编写LoadRunner脚本
    基于PHP+MySQL健身俱乐部系统的设计与实现
  • 原文地址:https://blog.csdn.net/qq_57828911/article/details/132720784