LeetCode 精选 TOP 面试题(Java 实现)—— 三数之和

一、题目描述

1.1 题目
  • 三数之和

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

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
1.2 知识点
  • 双指针
1.3 题目链接

二、解题思路

2.1 自研思路

  这道题在半年之前做过一次,现在算来也是第三次见到了,思路比较清晰就是使用双指针来解决,将其从三数之和的 a+b+c=0 转换为 a+b=-c 即搜索 a+b 两数之和为定值 -c 的数字组合。但是关键点在于怎样选择 -c 这个固定值,开始的时候我想选择两个指针中间的位置,然后将两个指针的对应的值固定,来在其中间遍历查找 -c ,但是遇到了一些问题。所以改变思路后,选择使用最左边为 -c ,然后该 -c 下标的左边首点为左指针,而整个数组的最右边为右指针,然后双指针移动查找和为 -c 的数字组合,每次查找完即将 -c 固定值的指针左移一位,然后再进行上述查找。

  对于算法优化主要在于:

  • 去重策略的选择,尽量不要选择遍历整个结果数组来去重,复杂度太高;
  • 剪枝优化,当 c 固定值和左指针及左指针左邻值相加就已经大于零或 c 固定值和右指针及右指针右邻值相加就已经小于零时,注定该轮双指针遍历不会得到结果,所以可以直接进行剪枝操作;

三、实现代码

3.1 自研实现
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        int left = 0, right = 0, target = 0;

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

            target = -nums[i];
            left = i + 1;
            right = nums.length-1;

            // 剪枝 48ms -> 34ms ; 时间击败87% ; 内存击败94% 
            if(nums[i]+nums[left]+nums[left+1] > 0 || nums[i]+nums[right]+nums[right-1] < 0 )
                continue;

            while(left < right) {

                if(nums[left]+nums[right] == target){
                    List<Integer> list = new ArrayList<Integer>();
                    list.add(nums[i]);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    res.add(list);

					// 去重并移动左指针
                    do left++;
                    while(left < right && left != right-1 && nums[left] == nums[left-1]);

					// 去重并移动右指针
                    do right--;
                    while(left < right && left != right-1 && nums[right] == nums[right+1]);
                        
                } else if(nums[left]+nums[right] < target)
                    left++;                
                else
                    right--;
            }
            // 去重
            while(i < nums.length-2 && nums[i] == nums[i+1]) i++;
        }
        return res;
    }
}
发布了244 篇原创文章 · 获赞 32 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_40697071/article/details/103916117