• 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) ]

  • 相关阅读:
    防窜货下加密锁使用常见问题
    SQL Server 2000/2005/2008 触发器的管理和查看
    列表显示时,部分凭证会分两行显示,且不能删除
    JDBC 连接 带实例名的SQL Server
    登录软件提示:读取数据源出现错误,pkcs7填充无效,无法被移除
    完美卸载SQL Server 2008的方案
    彻底卸载(删除)SQL server2000
    NCV5取消:授权数到达,或者许可证过期提示的秘诀
    SQL Server日志清空方法 .
    第二天 一列布局
  • 原文地址:https://www.cnblogs.com/tbgatgb/p/11096439.html
Copyright © 2020-2023  润新知