15、三数之和

image.png

(※这道题有点复杂——中等题)
思路:
1)先对数组进行排序,排序后固定一个数nums[i],在使用左右指针指向nums[i]后面两端,分别是nums[L]和nums[R],计算三个数的和是否满足nums[left]+nums[right]==target,如果满足,添加到结果集
2)如果nums[i]大于0,则三数之和必然大于0,结束循环
3)如果nums[i] == nums[i-1],则说明该数字重复,会导致结果重复,所以应该跳过。
4)nums[left]+nums[right]==target时,nums[L] == nums[L+1],会导致结果重复,所以应该跳过,L++
5)nums[left]+nums[right]==target时,nums[R] == nums[R−1] 则会导致结果重复,应该跳过,R−−

public static List<List<Integer>> threeSum(int[] nums){
        //总时间复杂度:O(n^2)
        List<List<Integer>> ans = new ArrayList<>();
        if (nums == null || nums.length <=2) {
            return ans;
        }

        Arrays.sort(nums);//O(nlogn)

        for (int i = 0; i <nums.length-2 ; i++) {//O(n^2)
            if (nums[i]>0) {
                break;//第一个数大于0,后面的数都比他大,肯定不成立
            }
            if (i>0 && nums[i] == nums[i-1]) {
                continue; //去掉重复的情况
            }
            int target = -nums[i];
            int left = i+1, right = nums.length-1;
            while(left<right){
             if (nums[left]+nums[right]==target){
                 ans.add(new ArrayList<>(Arrays.asList(nums[i],nums[left],nums[right])));

                 //现在要增加left,减小right,但是不能重复,比如: [-2, -1, -1, -1, 3, 3, 3], i = 0, left = 1, right = 6, [-2, -1, 3] 的答案加入后,需要排除重复的 -1 和 3
                 left++;right--;// 首先无论如何先要进行加减操作
                 while (left<right && nums[left] == nums[left-1]) {
                     left++;
                 }
                 while (left<right && nums[right] == nums[right+1]) {
                     right--;
                 }
             }else if (nums[left] + nums[right]<target){
                 left++;
             }else {//nums[left] +nums[right] >target
                 right--;
             }
            }
        }
        return ans;
    }
}

时间复杂度:O(n2),数组排序O(NlogN),遍历数组O(n),双指针遍历O(n),总体O(NlogN)+O(n)*O(n),O(n2)

空间复杂度:O(1)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容