zoukankan      html  css  js  c++  java
  • 刷题(Python) 三数之和

    本题出自力扣,难度:中等

    题目:

    给你一个包含 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

    需要注意,当数据量过大时超时的问题,参考大神们的解法,自己理解了一下,详细看注释

    class Solution(object):
        def threeSum(self, nums):
            """
            :type nums: List[int]
            :rtype: List[List[int]]
            """
            a = []
            # 先排序
            nums.sort()
            # nums元素小于3,则不成立,直接返回[]
            if len(nums) < 3:
                return []
            # 排序后,第一个元素大于0或者最后一个元素小于0,则肯定不成立,返回[]
            if nums[0] > 0 or nums[-1] < 0:
                return []
    
            # 循环列表,最后两位元素就不用循环了(因为需要3个数相加)
            # 现在假设,v是第一位数字,t是第二位数字的下标,j是第三位数字的下标
            for k,v in enumerate(nums[:-2]):
                # 如果元素大于0后,就跳出循环,因为后面的数大于0
                if v > 0:
                    break
                # 如果 k不等于0 而且 前一个元素等于现在的元素,就跳出此次循环
                if k != 0 and nums[k-1] == v:
                    continue
    
                # t是左边开始移动的数字(初始值为最左边第二位)
                # j是右边开始移动的数字(初始值为最右边第一位)
                t = k  + 1
                j = len(nums) - 1
                # 当左边开始移动的数字小于右边开始移动的数字下标时循环
                while t < j:
                    # 计算三位数字之和
                    s = v + nums[t] + nums[j]
                    # 如果三位数之和小于0,因为第一位数字在这个循环是固定的,就要找更大的数字,即最二位数字向右移(列表由小到大排序)
                    if s < 0:
                        t += 1
                        # 如果右移时,出现相同的数字,就要跳过(不用重复计算),且下标加一
                        while t < j and nums[t] == nums[t-1]:
                            t += 1
                    # 如果三位数之和大于0,因为第一位数字在这个循环是固定的,就要找更小的数字,即第三位数字向左移(列表由小到大排序)
                    elif s > 0:
                        j -= 1
                        # 如果左移时,出现相同的数字,就要跳过(不用重复计算),且下标加一
                        while t < j and nums[j] == nums[j+1]:
                            j -= 1
                    # 如果等于0,则加入a列表,因为单纯向右移动第二位(变大)或左移第三位(变小),三个数之和都会只会单纯的变大或变小,所以第二位向右移第三位向左移,同样,出现重复数字,则跳过且下标加一或减一
                    else:
                        a.append([v,nums[t],nums[j]])
                        t += 1
                        j -= 1
                        while t < j and nums[t] == nums[t-1]:
                            t += 1
                        while t < j and nums[j] == nums[j+1]:
                            j -= 1             
            return a  
    

      

  • 相关阅读:
    IOS开发——01_第一个OC程序
    01_iOS开发需要准备什么?
    正则表达式随笔
    .net4.6版本前设置window子窗口位置主窗口闪烁
    [CF1486D] Max Median
    [CF1487D] Pythagorean Triples
    [CF1487E] Cheap Dinner
    [CF1490E] Accidental Victory
    [CF1490F] Equalize the Array
    [CF1490G] Old Floppy Drive
  • 原文地址:https://www.cnblogs.com/mingmingming/p/15667884.html
Copyright © 2011-2022 走看看