题解 | #三数之和#

三数之和

http://www.nowcoder.com/practice/345e2ed5f81d4017bbb8cc6055b0b711

1.双指针遍历

class Solution:
    def threeSum(self, num: List[int]) -> List[List[int]]:
        if len(num) < 3:
            return []
        num.sort()
        res, i = set(), 0
        # 外层目标指针循环 用while可以跳过重复的目标值
        while i < len(num):
            # 定义左右指针指向头尾
            left, right = 0, len(num) - 1
            # 双指针开始循环
            while left < right:
                # 若目标指针与左指针重叠则跳过
                if i == left:
                    left += 1
                # 若目标指针与右指针重叠则跳过
                elif i == right:
                    right -= 1
                # 若目标值与左右指针值和为0,则排序后将元组记入集合res
                elif num[i] + num[left] + num[right] == 0:
                    t = [num[i], num[left], num[right]]
                    t.sort()
                    res.add(tuple(t))
                    left += 1
                    right -= 1
                # 小于0,左指针右移
                elif num[i] + num[left] + num[right] < 0:
                    # 加速左指针右移,跳过重复值
                    while left + 1 < right and num[left + 1] == num[left]:
                        left += 1
                    left += 1
                # 大于0,左右指针左移
                elif num[i] + num[left] + num[right] > 0:
                    # 加速右指针左移,跳过重复值
                    while right - 1 > left and num[right - 1] == num[right]:
                        right -= 1
                    right -= 1
            # 加速目标指针右移,跳过重复值
            while i + 1 < len(num) and num[i + 1] == num[i]:
                i += 1
            i += 1
        # 将set中的元组转化为列表
        result = []
        while res:
            result.append(list(res.pop()))
        return result


2.分类讨论,分为全零/正负零/正正负/正负负进行讨论

class Solution:
    def threeSum(self, num: List[int]) -> List[List[int]]:
        if len(num) < 3:
            return []
        # 记录去重后的正数/负数以及0的个数
        numz,numf,num0= set(),set(),0
        # 记录每个数字出现个数
        hashset = {}
        # 遍历分组
        for i in num:
            if i in hashset:
                hashset[i] += 1
            else:
                hashset[i] = 1
            if i > 0:
                numz.add(i)
            elif i < 0:
                numf.add(i)
            else:
                num0 += 1
        # 转为列表快排
        numz,numf = list(numz),list(numf)
        numz.sort()
        numf.sort()
        # 定义最终集合rst
        rst = set()
        # 取0,0,0时
        if num0 >= 3:
            rst.add(tuple([0, 0, 0]))
        # 取正,负,0
        if num0 > 0:
            # 定义正数数组numz左指针,定义负数数组numf右指针
            left,right = 0,len(numf) - 1
            # 双指针开始遍历
            while left < len(numz) and right >= 0:
                if numz[left] + numf[right] == 0:
                    # 指定顺序为负,0,正
                    rst.add(tuple([numf[right], 0, numz[left]]))
                    left += 1
                    right -= 1
                elif numz[left] + numf[right] < 0:
                    left += 1
                elif numz[left] + numf[right] > 0:
                    right -= 1
        # 取正,正,负
        for i in range(len(numz)):
            for j in range(len(numf)):
                # 定义目标值t
                t = -numf[j] - numz[i]
                # 若t为非正数,直接跳过
                if t <= 0:
                    continue
                # 若t不在hashset中,直接跳过
                if t in hashset:
                    # 若t与正数不相同
                    if t != numz[i]:
                        # 指定从小到大的顺序
                        if numz[i] > t:
                            rst.add(tuple([numf[j], t, numz[i]]))
                        else:
                            rst.add(tuple([numf[j], numz[i], t]))
                    # 若t与正数相同,判断数组***有几个t,避免一值多用
                    else:
                        if hashset[t] > 1:
                            rst.add(tuple([numf[j], numz[i], t]))

        # 取负负正 过程同上
        for i in range(len(numf)):
            for j in range(len(numz)):
                t = -numz[j] - numf[i]
                if t >= 0:
                    continue
                if t in hashset:
                    if t != numf[i]:
                        if t < numf[i]:
                            rst.add(tuple([t, numf[i], numz[j]]))
                        else:
                            rst.add(tuple([numf[i], t, numz[j]]))
                    else:
                        if hashset[t] > 1:
                            rst.add(tuple([numf[i], t, numz[j]]))
        # 将set中的元组转化为列表
        result = []
        while rst:
            result.append(list(rst.pop()))
        return result

全部评论

相关推荐

05-30 18:54
武汉商学院 Java
湫湫湫不会java:先投着吧,大概率找不到实习,没实习的时候再加个项目,然后把个人评价和荣誉奖项删了,赶紧成为八股战神吧,没实习没学历,秋招机会估计不多,把握机会。或者说秋招时间去冲实习,春招冲offer,但是压力会比较大
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务