刷题记录:数组问题

本文讲解如何使用Java通过排序和双指针技巧解决给定整数数组中是否存在三元组和为零的问题,包括去重策略和边界条件处理。

三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请:你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

=========================================================================

看到这个题目的第一想法是排序,排序可以有效的减少运算次数。java中数组排序被封装到Arrays包装类中,使用Arrays.sort(nums);即可实现排序。

排序之后怎么办呢?笔者到这里已经不会了,看一看题解吧!

题解:

1.对数组进行排序。
2.遍历排序后数组:
若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
对于重复元素:跳过,避免出现重复解
令左指针 L=i+1,右指针 R=n-1,当 L<R 时,执行循环:
当 nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R移到下一位置,寻找新的解。
若和大于 0,说明 nums[R] 太大,R 左移。
若和小于 0,说明 nums[L]太小,L 右移。

看了题解之后感叹我还是太嫩了,这个思路在我脑子里想出来了前一半,但是后一半没没有想清楚。自己按照思路尝试编写一下。

class Solution {

    public List<List<Integer>> threeSum(int[] nums) {

        int i = 0; 

        int j, k;

        List<List<Integer>> res = new ArrayList<>();

        Arrays.sort(nums);

        while (i < nums.length && nums[i] <= 0) {

            j = i + 1;

            k = nums.length - 1;

            while(j < k) {

                if (nums[i] + nums[j] + nums[k] < 0) {

                    j++;

                } else if (nums[i] + nums[j] + nums[k] > 0) {

                    k--;

                } else {

                    res.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[j], nums[k]))); 

                    //去重

                    while (nums[j] == nums[j + 1]) j++;

                    while (nums[k] == nums[k - 1]) k--;

                }

                j++;

                k--;

            }

            i++;

        }

        return res;

    }

}

经过运行,存在各种各样的边界值问题,去重过程的溢出,nums[i]没有考虑去重等。参照标准解答进行学习。

class Solution {

    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> res = new ArrayList<>();

        Arrays.sort(nums);

        for (int i = 0; i < nums.length - 2; i++) {

            if (nums[i] > 0) break;

            //去重,对脚标做加减运算,一定要附加边界限定!采用i > 0的判定,相比于i < nums.length效率要高。要学会反向思考问题

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

            int j = i + 1;

            int k = nums.length - 1;

            while(j < k) {

                int sum = nums[i] + nums[j] + nums[k];

                if (sum < 0) {

                    //去重

                    /*对脚标做加减运算,一定要附加边界限定!*/

                    while (j < k && nums[j] == nums[++j]);

                } else if (sum > 0) {

                    while (j < k && nums[k] == nums[--k]);

                } else {

                    res.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[j], nums[k]))); 

                    while (j < k && nums[j] == nums[++j]);

                    while (j < k && nums[k] == nums[--k]);

                }

            }

        }

        return res;

    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值