首页 > 其他分享 >LeetCode - 三数之和

LeetCode - 三数之和

时间:2022-08-23 11:00:09浏览次数:77  
标签:right nums int 三数 复杂度 数组 LeetCode left

题目信息

源地址:三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 abc ,使得 a + b + c = 0,请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

提示信息

示例 1

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2

输入:nums = []
输出:[]

示例 3

输入:nums = [0]
输出:[]

限制

  • 0 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

实现逻辑

暴力枚举

最先想到的应该是暴力枚举的方法,当然这也是最简单的的方法。

既然这里要找出符合要求的三个数,当然是使用三层循环依次去匹配,缺点就是时间复杂度达到了 \(O(n^3)\),当数组长度特别长的时候,程序运行时间也会特别长。

哈希匹配

从“两数之和”题目中可以知道,使用哈希表结构采用空间换时间的方式,时间复杂度能从 \(O(n^2)\) 降到了 \(O(n)\)。

如果将这种空间换时间的方式代入这个题目,可以将暴力破解 \(O(n^3)\) 的时间复杂度降到 \(O(n^2)\),这也是一个非常大的提升。

排序 + 双指针

现在思考一下如何将时间复杂度从 \(O(n^2)\) 降下去。

  1. 首先一层循环是必不可少的,因为至少要对给定的数组做一次枚举;
  2. 假如拿到数组的第一个元素,需要思考一下怎么从数组剩下的元素中找到匹配的两个元素,换一个思路其实就是从剩下的数组元素中找到和等于第一个元素相反数的两个元素,所以这里退变成了“两数之和”的逻辑;
  3. 如果对剩下的元素采用哈希匹配的方法,其实就和上面的方法一致了,由于答案中不可以包含重复的三元组,这里先对数组进行排序,方便后续跳过相同的答案,再采用数组首尾双指针的方法查找匹配的两个数。
package cn.fatedeity.algorithm.leetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ThreeSum {
    public List<List<Integer>> answer(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            if (i != 0 && nums[i] == nums[i - 1]) {
                // 答案不可以包含重复的三元组,这里相同的数直接过掉
                continue;
            }
            int target = -nums[i];
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                int diff = target - (nums[left] + nums[right]);
                if (diff > 0) {
                    left++;
                } else if (diff < 0) {
                    right--;
                } else {
                    boolean leftFlag = left == 0 || nums[left] != nums[left - 1];
                    boolean rightFlag = right == nums.length - 1 || nums[right] != nums[right + 1];
                    if (leftFlag || rightFlag) {
                        // 这里的 if 判断仍然是避免答案出现重复的三元组
                        List<Integer> list = new ArrayList<>();
                        list.add(nums[i]);
                        list.add(nums[left]);
                        list.add(nums[right]);
                        result.add(list);
                    }
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
}

使用这个方式解决这个题目,耗时的地方有两个:对原数组进行排序;对排序后的数组查找出和为目标数的两个数。

排序的时间复杂度可以看做是 \(O(n\log_2n)\),查找出剩余两个数采用了遍历数组并嵌套使用双指针遍历,时间复杂度为 \(O(n \times n)\),最终总体的时间复杂度在 \(O(n^2)\)。

在整个过程当中,除了存储答案需要额外的空间,实际的空间复杂度是 \(O(1)\)。

标签:right,nums,int,三数,复杂度,数组,LeetCode,left
From: https://www.cnblogs.com/fatedeity/p/16615378.html

相关文章

  • leetcode68-文本左右对齐
    文本左右对齐模拟先对所有字符串进行一次遍历,保证每个字符串之间有一个空格,然后对字符串分组,确定字符串的位置。然后对每一组的字符串分配空格:遍历这一组的字符串长度......
  • LeetCode/变为棋盘
    一个 nxn 的二维网络 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置返回将这个矩阵变为 “棋盘”  所需的最小移动次数 ,如果不存在......
  • [Oracle] LeetCode 1802 Maximum Value at a Given Index in a Bounded Array
    Youaregiventhreepositiveintegers:n,index,andmaxSum.Youwanttoconstructanarraynums(0-indexed)thatsatisfiesthefollowingconditions:nums.len......
  • [Google] LeetCode 1610 Maximum Number of Visible Points 极角排序
    Youaregivenanarraypoints,anintegerangle,andyourlocation,wherelocation=[posx,posy]andpoints[i]=[xi,yi]bothdenoteintegralcoordinateson......
  • LeetCode 593. 有效的正方形(向量做法)
    题目题目链接:593.有效的正方形题意:给出二维平面上四个点的坐标,判断这四个点是否能构成一个正方形,四个点的输入顺序不做任何保证。思路通过向量运算可以很轻松地解决这......
  • leetcode48-旋转图像
    旋转图像原地旋转将正方形的数组切分成一个个圈,然后对这个圈进行移动classSolution{publicvoidrotate(int[][]matrix){intn=matrix.length;......
  • LeetCode 367. 有效的完全平方数
    LeetCode367.有效的完全平方数思路:核心为最后一步判断当二分结束后值为及接近一个整数的浮点数(如2.9xxxx)此时加上极小数(1e-6)取整再平方,若与num相等则为完全平方数......
  • LeetCode 69. x 的平方根
    LeetCode69.x的平方根思路:浮点数二分修改版因为返回的是整数所以二分分三类讨论mid*mid==x该情况mid为x的平方根mid*mid>x该情况mid大于x的平方根mid......
  • LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置
    34.在排序数组中查找元素的第一个和最后一个位置思路:与AcWing789一致classSolution{public:vector<int>searchRange(vector<int>&nums,inttarget){......
  • LeetCode 35. 搜索插入位置
    LeetCode35.搜索插入位置思路直接利用二分模板注意右指针开始为nums.size()而不是nums.size()-1因为有可能在最后一位插入classSolution{public:intsearc......