zoukankan      html  css  js  c++  java
  • leetcode hot 100-15. 三数之和

    15. 三数之和

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

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

    示例:

    给定数组 nums = [-1, 0, 1, 2, -1, -4],
    
    满足要求的三元组集合为:
    [
    [-1, 0, 1],
    [-1, -1, 2]
    ]

    思路:双指针法

    思路参考:https://leetcode-cn.com/problems/3sum/solution/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/

    总体思路:对于每个数nums[i], 判断它后面是否存在两个数,使得这两个数加上 nums[i] 的和刚好为0
    具体实现过程:
    先对nums[]数组进行排序
    遍历nums[]数组,对于每个数nums[i], 判断它后面是否存在两个数,使得这两个数加上 nums[i] 之后的和刚好为0

    如果nums[i]大于0, 因为nums[ ]数组已经按从小到大排序,所以可以断定nums[i]后面不存在两个数能使的三数之和等于0,且nums[i]后面的元素也不符合条件,不需要继续枚举下去,直接 break 跳出循环。

    如果nums[i] == nums[i-1],无论nums[i]是否存在合法解,它的所有合法情况都已经在nums[i-1]被枚举过了,所以应该跳过。

    开始寻找符合条件的解:让左指针等于i+1, 右指针等于len - 1

    • 如果三数之和大于0, 右指针应该左移使得和能够减小一些
    • 如果三数之和小于0, 左指针应该右移使得总和能够增大一些
    • 如果三数之和等于0, 说明找到了一个合法的解,记录下来,此时,如果nums[left] = nums[left+1], left应该后移一位,因为nums[i]已经固定了,如果nums[left+1]也和上一个解一样的话,则剩下的一个数肯定也是一样的,则此次统计的一定是一个重复解,同理右指针
     1 class Solution {
     2     public List<List<Integer>> threeSum(int[] nums) {
     3 
     4         List<List<Integer>> res = new ArrayList<>();
     5         if(nums == null || nums.length == 0){
     6             return res;
     7         }
     8 
     9         Arrays.sort(nums);  // 排序
    10 
    11         int len = nums.length;
    12         for(int i = 0; i < len; i++){
    13             if(nums[i] > 0){
    14                 break;
    15             }
    16             if(i > 0 && nums[i] == nums[i-1]){  // 去重
    17                 continue;
    18             }
    19             int left = i + 1, right = len - 1;
    20             while(left < right){
    21                 int sum = nums[i] + nums[left] + nums[right];
    22                 if(sum == 0){ //如果三数之和等于0, 说明找到了一个合法的解,记录下来,
    23                     res.add(Arrays.asList(nums[i], nums[left], nums[right]));
    24                     while(left < right && nums[left] == nums[left + 1]){  // 跳过重复元素
    25                         left++;
    26                     }
    27                     while(left < right && nums[right] == nums[right-1]){    // 跳过重复元素
    28                         right--;
    29                     }
    30                     left++;
    31                     right--;
    32                 }else if(sum > 0){ //如果三数之和大于0, 右指针应该左移使得和能够减小一些
    33                     right--;
    34                 }else{  //如果三数之和小于0, 左指针应该右移使得总和能够增大一些
    35                     left++;
    36                 }
    37             }
    38         }
    39         return res;
    40     }
    41 }

    leetcode 执行用时:23 ms > 84.00%, 内存消耗:42 MB > 97.62%

    复杂度分析:

    时间复杂度:O(n2)。排序的时间复杂度为O(nlogn)。接下来循环遍历每个nums[i], 使用双指针法遍历这个nums[i]后面的所有元素是否存在符合条件的解,双指针的复杂度为O(n), 所以总的时间复杂度为O(n2)。

    空间复杂度:O(1)。除了存储结果的列表,其他的变量空间都是常数级别的, 所以空间复杂度为O(1)。

  • 相关阅读:
    解压tar.gz文件报错gzip: stdin: not in gzip format解决方法
    通过 HTTP 头进行 SQL 注入(转)
    Android涉及到的设计模式(转)
    初探Java8中的HashMap(转)
    substance的使用示例(转)
    大数据量下高并发同步的讲解(不看,保证你后悔)(转)
    HDU 4812 D Tree 树分区+逆+hash新位置
    在weblogic11g发布该项目时遇到错误(不支持web-app_3_0)
    highchart几个图表马金摘要
    android 使用 service 实现音乐
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/13945527.html
Copyright © 2011-2022 走看看