zoukankan      html  css  js  c++  java
  • 1-1

    15.三数之和

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

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

    例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

    满足要求的三元组集合为:
    [
    [-1, 0, 1],
    [-1, -1, 2]
    ]

    Python most votes solution:

    class Solution(object):
        def threeSum(self, nums):
            """
            :type nums: List[int]
            :rtype: List[List[int]]
            """
            res = []
            nums.sort()
            for i in xrange(len(nums)-2):
                if i > 0 and nums[i] == nums[i-1]:
                    continue
                l, r = i+1, len(nums)-1
                while l < r:
                    s = nums[i] + nums[l] + nums[r]
                    if s < 0:
                        l +=1 
                    elif s > 0:
                        r -= 1
                    else:
                        res.append([nums[i], nums[l], nums[r]])
                        while l < r and nums[l] == nums[l+1]:
                            l += 1
                        while l < r and nums[r] == nums[r-1]:
                            r -= 1
                        l += 1; r -= 1
            return res
    

    时间复杂度:(O(n^2))

    分析:

    • 首先排序,利用有序数组可以更快地找到想要的三元组;

    • xrange的用法

    • 第1个if判断从i=1开始生效,它的作用是跳过重复的元素。例如考虑如下序列:

      nums = [-1, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6]
      

      利用该if判断,程序会跳过前三个2,直接从第四个2开始运行if判断后面的程序,因为题目中要求答案中不可以包含重复的三元组,若不这样做则会产生重复的三元组;

    • lr可以看做是左右两个指针,如果s < 0,则左指针l右移,使其指向更大的数;同理,如果s > 0,则右指针r左移,使其指向更小的数;

    • 如果s = 0,则说明找到了想要的三元组,此时第一步操作是先将它们放进res中,因为有可能nums中满足题意的三元组并非只有这一组,因此要继续做判断:

      • 在左指针依旧在右指针左侧的前提下,

        (1)若左指针指向的当前位置的元素和它指向的下一个位置的元素(即左指针右移一位之后指向的元素)相等(此时就会出现题目中提到的“重复”的情况),因此要删除这种重复的情况。具体做法就是让左指针往右移一位就可以了。

        (2)同理,若右指针指向的当前位置的元素和它指向的下一个位置的元素(即右指针左移一位之后指向的元素)相等,就又会出现重复的情况,删除这种重复情况的方法是让右指针左移一位。

        (3)若终于左右指针均不再重复了(即下述nums序列中,左指针已经指向了从左往右数的最后一个2,右指针已经指向了从右往左数的最后一个4),则让左指针右移一位,同时右指针左移一位,继续在while循环中做判断。

        nums = [-1, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6]
        
    • 整个for循环总共要执行(n-2)次(i的值从nums中第一个元素nums[0]一直遍历到倒数第二个元素nums[n-3]

    • 在每一次进入while循环之前,左右指针的位置都会被重新定向,使左指针指向nums[i]右边紧邻的一个元素nums[i+1],右指针指向最后一个元素nums[n-1]。整个while循环会执行的次数为

      [(n-1) - (i + 1) - 1 = n - i -3 ]

    • 因此,算法的整体时间复杂度为

      [O(n-2) imes O(n - i -3) approx O(n^2) ]

  • 相关阅读:
    【python练习】选课系统(基于面向对象的)
    【面向对象】类的特殊成员方法
    【面向对象】属性方法
    【面向对象】类方法
    【面向对象】静态方法
    【python练习】计算器(使用正则表达式实现)
    【面向对象】多态
    【面向对象】新式类和旧式类的区别
    re.findall()正则表达式中括号的坑
    您真的了解javaScript?(2)
  • 原文地址:https://www.cnblogs.com/tbgatgb/p/11096439.html
Copyright © 2011-2022 走看看