3. <tag-数组和双指针(左右指针)>-leetcode.15-三数之和 + leetcode.167-两数之和 II

1. LeetCode 15. 三数之和 (Medium)

[案例需求]
在这里插入图片描述

[思路分析]

  1. 这道题可以看做是两数之和的更进一步, 所以根据两数之和的高级解法, 我们可以对三数之和使用hashMap法, 或者使用双指针中的左右指针法, 显然这道题, 包括前面的两数之和, 使用左右双指针都是比较容易理解的;
  2. 本题目中未声明数组有序, 所以实现还需要对数组进行排序, 同时最最最重要的一点就是对数组中重复数字的处理, 在开始遍历第一个加数之前, 我们需要对第一个加数进行去重, 在遍历第一个加数之后, 我们还需要对第二个和第三个加数进行去重!!! 怎么去重? 遇到这个数跟前面一个数一样大的时候, 跳过这个数即可;
  3. 说了老半天, 整体思路是:
    1. 先对数组进行排序,
    2. 循环遍历数组的第一个加数(从0–>nums.length-2(不含), 因为还要留出后两个加数嘛),
    3. 第一个加数去重, 与前面的一个数比较, 重复则跳出本次循环(continue]);
    4. 每次遍历第一个加数时, 使用左右指针作为后两个加数遍历剩下的数;
    5. nums[L] + nums[R] + nums[i] < 0, 移动左指针.
    6. nums[L] + nums[R] + nums[i] > 0, 移动右指针.
    7. 当发现nums[L] + nums[R] + nums[i] == 0时, 我们先对nums[L],nums[R]进行去重, 然后再执行添加到list, 移动指针的一系列操作, 切记, 去重非常非常重要!!!

[代码实现]

class Solution {
    
    
	public List<List<Integer>> threeSum(int[] nums) {
    
    
		List<List<Integer>> lists  = new  ArrayList<>();
		if(nums == null || nums.length  < 3) return lists;
        Arrays.sort(nums);
        int target,L,R;
		for(int i = 0; i < nums.length-2; i++){
    
    
            target = 0 - nums[i];
            L = i + 1;
            R = nums.length - 1;          
            if(nums[i] >0 ) return lists;
            if(i> 0 && nums[i] == nums[i-1]) continue;
            while( L < R){
    
    
                 if(nums[L] + nums[R] > target)R--;
                if(nums[L] + nums[R] < target)L++;

                if(L != R && nums[L] + nums[R] == target){
    
    
                    //对后面的加数去重
                    while(L < R && nums[L] == nums[L+1]) ++L;
                    while(L < R && nums[R] == nums[R-1]) --R;
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[L]);
                    list.add(nums[R]);
                    lists.add(list);
                    L++;
                    R--;
                }
            }
        }
		return lists;
	}
}

1. LeetCode 167. 两数之和II- 输入有序数组 (easy)

[案例需求]
在这里插入图片描述

[思路分析]

  1. 前面tag数组-刷题预备知识-3 一文总经提到过, 一般给你有序数组, 用双指针解题的较多;
  2. 本题两数之和, 即是采用左右双指针法解题, 可以达到O(n)的数据复杂度;
  3. 大体思路如下:
    1. L–左指针, 数组的开头.
    2. R–有指针, 数组的末尾.
    3. nums[L] + nums[R] > target, 移动右指针 R–;
    4. nums[L] + nums[R] < target, 移动左指针, L++;
    5. nums[L] + nums[R] == target, 找到, 返回即可;

[代码实现]

class Solution{
    
    
	public int[] twoSum(int[] numbers, int target) {
    
    
        //有序的数组中找出两个数相加为target, 左右指针走起
        int L = 0;
        int R = numbers.length - 1;
        
        while(L < R){
    
    
            if(numbers[L] + numbers[R] < target)
                L++;
            if(numbers[L] + numbers[R] > target)
                R--;

            if(numbers[L] + numbers[R] == target)
                return new int[]{
    
    L+1, R+1};
        }
        return new int[]{
    
    };
    }
}

猜你喜欢

转载自blog.csdn.net/nmsLLCSDN/article/details/121244105
今日推荐