【leetcode学习记录】

----学习记录-----

三数之和

方法:排序+双指针
基本思想:将三个数下标分别设置为i,L,R,在循环过程中要保证三个数的相对顺序,即i < L < R。
i:遍历数组的下标
L:初始值为i+1
R:初始值为数组大小-1
循环中每次第一个数字i都是确定的,L为最靠近i的左指针,R为数组最右侧的右指针,当L<R时进行内部循环,如果三数之和>0,R指针向左移(R值减小),如果三数之和<0,L指针向后移(L值增大),如果三数之和=0,将其存入结果中。
难点:判断重复
对于i:每次外层循环的开始判断此时的i和上一次循环的i是否相等,如果相等直接跳过此轮循环。(因为上一趟循环已经将i值确定的所有组合都遍历过了)
对于L,R:当内层循环找到三数之和=0的时候,判断L右侧的值是否等于L值,如果相等就将L向右移动,R情况类似。(因为此时i已经确定,所以L和R任何一方都不能出现重复数字)

//leetcode-15
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        Arrays.sort(nums);
        //i,L,R分别为三个数字
        for(int i = 0; i < nums.length; i++){
            if(nums[i] > 0) return lists;

            if(i > 0 && nums[i] == nums[i - 1]) continue;

            int L = i + 1;
            int R = nums.length - 1;
            while(L < R){
                int sum = nums[i] + nums[L] + nums[R];
                if(sum == 0){
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[L]);
                    list.add(nums[R]);
                    lists.add(list);
                    while(L < R && nums[L + 1] == nums[L]){
                        L++;
                    }
                    while(L < R && nums[R - 1] == nums[R]){
                        R--;
                    }
                    L++;
                    R--;
                }
                else if(sum > 0){
                    R--;
                }
                else{
                    L++;
                }
            }
        }
        return lists;
    }
}

四数之和

和三数之和类似,三数之和循环中确定的是第一个数的值,四数之和循环中确定的是前两个数的和值,内层循环同样通过L,R双指针降低时间复杂度。判断重复时注意同一重循环中,如果当前元素与上一个元素相同,则跳过当前元素。

//leetcode-18
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> lists = new ArrayList<>();
        Arrays.sort(nums);
        //i,j,left,right为四个不重复的数
        for(int i = 0; i < nums.length; i++){
            if(i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            for(int j = i + 1; j < nums.length; j++){
                if(j > i + 1 && nums[j] == nums[j - 1]){
                    continue;
                }
                int left = j + 1;
                int right = nums.length - 1;
                while(left < right){
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum == target){
                        List<Integer> list = new ArrayList<>();
                        list.add(nums[i]);
                        list.add(nums[j]);
                        list.add(nums[left]);
                        list.add(nums[right]);
                        lists.add(list);
                        while(left < right && nums[right - 1] == nums[right]){
                            right--;
                        }
                        while(left < right && nums[left + 1] == nums[left]){
                            left++;
                        }
                        right--;
                        left++;
                    }
                    else if(sum > target){
                        right--;
                    }
                    else{
                        left++;
                    }
                }
            }
        }
        return lists;
    }
}

未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值