15.三数之和

68 阅读1分钟

15. 三数之和 - 力扣(LeetCode)

用到的算法知识: 排序+双指针

遍历时当前下标,定住 作为符合条件第一个元素,然后双指针为l=i+1,r=n-1,代表剩余的两个元素。

算法思路

  1. 排序

  2. 特判,对于数组长度小于3的,返回[].

  3. 遍历数组

    • 若nums[i]>0: 因为已经排序好,所以后面的数都是正数,不可能存在符合条件的情况了
    • 循环双指针,条件l<r
      • 当sum>0 r--
      • 当sum<0 l++
      • 当sum==0 添加到答案中,并检查l,r的下一位是否与当前值相同,相同就跳过
    • 最后nums[i]也要跳过重复的元素
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList();
        //先将数组排好序,然后遍历i,双指针为l= i+1,r = n-1
        if(nums.length < 3)
            return ans;
        Arrays.sort(nums);
        for(int i  = 0; i < nums.length-2; i++) {
            if(nums[i] > 0)
                break;
            //在有序的区间中进行双指针遍历
            int l = i+1,r = nums.length-1;
            while(l<r){
                int sum = nums[i] + nums[l] + nums[r];
                if(sum>0) {
                    r--;
                }
                else if(sum<0){
                    l++;
                }
                else {
                    List<Integer> list = new ArrayList();
                    list.add(nums[i]);
                    list.add(nums[l]);
                    list.add(nums[r]);
                    ans.add(list);
                    //得到一种答案时,要跳过l,r中下一个重复的数,保证去重
                    while(l+1<nums.length&&l<r&&nums[l]==nums[l+1]){
                        l++;
                    }
                    while(r-1>=0&&l<r&&nums[r]==nums[r-1]){
                        r--;
                    }
                    l++;
                    r--;                
                }
            }
            //i也一样,跳过重复的数
            while(nums[i]==nums[i+1]&&i<nums.length-2)
                i++;
        }
        return ans;
    }
}