51-数组-三数之和-LeetCode15(python)

该博客主要探讨LeetCode第15题‘三数之和’的解决方案。博主首先介绍了问题描述和示例,然后分享了最初的暴力遍历思路以及遇到的元素重复和排序问题。通过网友的建议,博主采用了排序后遍历的方法,通过比较元素值和相邻元素,控制遍历指针避免重复和超时。在后续的复习中,博主还发现了对变量i的控制问题并进行了修正。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 题目描述

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

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

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

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
  • 解决思路

(1)最开始我的解决思路是使用暴力,从头开始遍历所有的元素,寻找满足条件的三元组并输出,编码之后发现输出的结果有问题,主要体现在元素没有排序,而且还会有重复的三元组出现。想到的解决方案是把数组变为set,然后再排序,之后再进行暴力的遍历,但是结果仍然不能通过,讨论区有很多回答说的是超时问题,我的答案却是索引的问题,这么看来按暴力解法的话,我的思路其实也不是那么完全正确,使用python,网友的解决方案如下:

(2)仍旧是先进行排序,排序之后进行遍历,在遍历的过程中,分别考虑三元组的三个元素,这三个元素都有可能遇到重复的数值,我们通过比较i,j,k分别对应的元素与相邻元素的值是否相同,控制i,j,k是否需要向后(i,j)或向前(k)移动。除此之外,通过判断当前三数之和与0的关系,可以决定j,k哪一个需要向前或向后移动。

(3)要特别注意对i的判断和控制,第二天复习时自己敲,发现了这个问题,对博客进行了修改。

  • 代码
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        if(len(nums)) < 3:
            return []
        #对数组排序
        nums.sort()
        #要返回的集合
        sets = []
        #遍历数组
        for i in range(len(nums)-2):
            #不可以用这种方式来进行判断
            # if (nums[i] == nums[i+1]):
            #     continue
            #原因在于i前边的元素肯定是参与过运算的,如果i和前一个相同,那么就没有必要再进行一次对j和k的遍历(第二个数和第三个数)
            #而i后边的元素是没有作为三元组的第一个数存在过的,如果判断i和i+1的大小的话,会忽略掉j = i+1的情况
            #其实是对第一个数字的控制,判断当前i对应的数字是否作为第一个数参与过遍历计算。如果判断i与i+1,则达不到这样的作用
            
            if(i>0 and nums[i] == nums[i-1]):
                continue
            #j是前边的指针
            j = i +1
            #k是后边的指针
            k = len(nums) - 1
            while(j<k):
                rr = nums[i]+nums[j]+nums[k]
                #如果三数之和等于0
                if(rr==0):
                    sets.append([nums[i],nums[j],nums[k]])
                    #考虑前边的指针遍历到相同的数值
                    while(j<k and nums[j] == nums[j+1]):
                        j += 1
                    #考虑后边的指针遍历到相同的数值
                    while(j<k and nums[k] == nums[k-1]):
                        k -= 1
                    j += 1
                    k -= 1
                #如果三数之和小于0,那么前边的指针向后移动(j指示的元素数值变大)
                elif(rr<0):
                    j += 1
                #如果三数之和大于0,那么后边的指针向前移动(k指示的元素数值变小)
                else:
                    k -= 1
        return sets
                        

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值