15. 三数之和

1.题目

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 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

2.解题思路

  • 方法一:排序 + 双指针
    标签:数组遍历
    首先对数组进行排序,排序后固定一个数nums[i,再使用左右指针指向numsi后面的两端,数字分
    别为nms[L]和nums[R],计算三个数的和sum判断是否满足为O,满足则添加进结果集
    如果nums[i大于0,则三数之和必然无法等于0,结束循环
    如果nums[i=nums[i-1],则说明该数字重复,会导致结果重复,所以应该跳过
    当sum=0时,nums[L]==numsL+1]则会导致结果重复,应该跳过,L++
    当sum=0时,numsR=nums[R-1]则会导致结果重复,应该跳过,R–
    时间复杂度:O(n2),n为数组长度

3.代码

object Solution {
    import java.util
  import scala.collection.mutable.{ArrayBuffer, ListBuffer}
  import scala.util.control.Breaks
  def threeSum(nums: Array[Int]): List[List[Int]] = {
    val listBuffer = new ListBuffer[List[Int]]()
    val len = nums.length
    if(nums == null || len<3)  return listBuffer.toList
    util.Arrays.sort(nums)   // 排序
    val loop = new Breaks
    val loop2 = new Breaks
    loop.breakable{
    for (i<-0 to len-1){
      loop2.breakable {
        if (nums(i) > 0) loop.break()
        if (i > 0 && nums(i) == nums(i - 1)) loop2.break() // 去重操作
        var L = i + 1
        var R = len - 1
        while (L < R) {
          val sum = nums(i) + nums(L) + nums(R)
          if (sum == 0) {
            listBuffer.append(List(nums(i), nums(L), nums(R)))
            while (L < R && nums(L) == nums(L + 1)) L = L + 1 // 去重操作
            while (L < R && nums(R) == nums(R - 1)) R = R - 1 // 去重操作
            L = L + 1
            R = R - 1
          }
          else if (sum < 0) L = L + 1
          else if (sum > 0) R = R - 1
        }
      }
    }
    }
     return listBuffer.toList
  }
}

4.复杂度分析

  • 时间复杂度:O(N2),其中N是数组nums的长度。
  • 空间复杂度:O(logN)。我们忽略存储答案的空间,额外的排序的空间复杂度为O(logN)。然而我们修改了输入的数组nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了nums的副本并进行排序,空间复杂度为O(N)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值