python--三数值之和

记录一下,用以自学

题目:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum

 

为了减低时间复杂度,我使出了洪荒之力,模仿两数之和,最后修改的代码为:

from typing import List
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 试试用第三个数找前面的数
        s=[]
        dict={}
        for i in range(len(nums)):
            otherNum=-nums[i]
            k=dict.get(otherNum)
            if k!=None:
                for j in k:
                    s0=sorted([nums[i],j[0],j[1]])
                    if s0 not in s:
                        s.append(s0)
            # 记录下这个数的所有组合
            for g in range(i):
                addedNum=nums[g]+nums[i]
                kg=dict.get(addedNum)
                if kg == None:
                    dict[addedNum]=[[nums[g],nums[i]]]
                else:
                    dict[addedNum].append([nums[g],nums[i]])
        return s

初略计算一下时间复杂度,如果不算

kg=dict.get(addedNum)

的时间复杂度是O(n2),但是应该是要算的,所以时间复杂度应该是O(n3),超时,呜呜呜呜,想不到更好的办法了

看解答:

答案的思路就是先排序,然后以类似双指针的方式,先遍历first,计算他需要的target,然后以双指针的方式去寻找加起来等于-target的second 和third

second从first+1开始,third从n-1开始,加起来比目标数大的话,third-1,加起来比目标数小的话,second+1,一旦second==third,本轮结束

题目要求不能重复输出,所以需要添加很多限制条件:

可以在选择的时候,筛选,但这样会比较慢,根据解答的思路写出来是这样子的

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        s=[]
        nums.sort()
        n=len(nums)
        for first in range(n):
            target=-nums[first]
            second=first+1
            third = n - 1
            while(second<third):
                t=nums[second]+nums[third]
                if t==target :
                    k=[nums[first],nums[second],nums[third]]
                    if k not in s:
                        s.append(k)
                    second+=1
                    third-=1
                elif(t<target):
                    second+=1
                else:
                    third-=1
        return s

可以通过判断second和third的关系来限制,增加了两个限制条件,两个条件是抄解答的,不是很理解

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        s=[]
        nums.sort()
        n=len(nums)
        for first in range(n):
            #为了防止重复
            if first > 0 and nums[first] == nums[first - 1]:
                continue
            target=-nums[first]
            second=first+1
            third = n - 1
            while(second<third):
                #为了防止重复
                if nums[second]==nums[second-1] and second-1!=first:
                    second+=1
                    continue
                t=nums[second]+nums[third]
                if t==target :
                    s.append([nums[first],nums[second],nums[third]])
                    second+=1
                    third-=1
                elif(t<target):
                    second+=1
                else:
                    third-=1
        return s
双指针的思路确实很有用,上一道题计算水的容量也用到了,那个时候也没想起来,顺便记一下:

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。


说明:你不能倾斜容器。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water

看解答后的代码

class Solution:
    def maxArea(self, height: List[int]) -> int:
        maxV = 0
        i,j=0,len(height)-1
        while(i!=j):
            li = height[i]
            lj = height[j]
            v=(j-i)*min(li,lj)
            if(maxV<v):
                maxV=v
            if(li<=lj):
                i+=1
            else:
                j-=1
        return maxV

双指针利用的是排序后的数据大小关系,容器的那道题利用的是x轴距离相差越大越好的特点。

posted @ 2022-03-23 23:58  moondays  阅读(148)  评论(0)    收藏  举报