leetcode解题报告- 2Sum/3Sum/4Sum

本贴最后更新于 2318 天前,其中的信息可能已经斗转星移

##1.Two Sum

  • 难度:Medium

  • 题目大意:
    给定一个整数数组,要求找出数组中两数和为指定数字,返回这两个数的索引。 假定有且只有一个解。

  • 思路:
    这道题的关键在于如何快速找到 taget-n 的索引,直接扫肯定太慢,当然用哈希表最快。这道题的陷阱在于,注意同一个数不能用两次,需要判断索引是否相同。若同一个数出现多次,记录最后出现的索引位置即可,因为有上面那个判断,可以区分出这个一个数字出现多次的情况。
    这种解法的时间复杂度为 O(n),遍历一次数组,循环中查哈希表复杂度为 1。

  • 代码:

    class Solution: # @param {integer[]} nums # @param {integer} target # @return {integer[]} def twoSum(self, nums, target): dic={} for i,n in enumerate(nums): dic[n]=i for i,n in enumerate(nums): if target-n in dic and dic[target-n]!=i: return[i,dic[target-n]]

##15.3Sum

  • 难度:Medium

  • 题目大意:
    给定一个整数数组,找出所有能使 a+b+c=0 三元组。注意,元组中按正序排列,不允许重复元组出现。
    思路 1:
    3 个数和为 0,那么必有以下推断:有 1 个数字 <=0,有 1 个数 >=0。因此,我采用以下解法。先将数组排序(nlogn),找到 <=0 和 >0 的分界点 dis。第一个数字 firstn 遍历[0,dis),第二个数字 secondn 循环遍历(firstn,len-1),然后在数组(secondn,len-1)中二分查找第三个数字。看似有 2 重循环 + 二分查找,但是由于我们经过了大量的剪枝,所有实际上复杂度没有那么高。

  • 代码:

    class Solution: # @param {integer[]} nums # @return {integer[][]} def threeSum(self, nums): #print(datetime.datetime.now()) result = [] if len(nums)<3: return result nums.append(1) nums.sort() dis = self.binarySearch(nums,0,len(nums)-1,1) nums.remove(1) for firstn in range(dis): for secondn in range(firstn+1,len(nums)-1): thirdn = self.binarySearch(nums,secondn+1,len(nums)-1,0-(nums[firstn]+nums[secondn])) if thirdn != -1: if[nums[firstn],nums[secondn],nums[thirdn]] not in result: result.append([nums[firstn],nums[secondn],nums[thirdn]]) return result #binary search def binarySearch(self,nums,i,j,n): if n<nums[i] or n>nums[j] or i>j: return -1 mid = (i+j)//2 if n == nums[mid]: return mid elif n < nums[mid]: return self.binarySearch(nums,i,mid-1,n) else: return self.binarySearch(nums,mid+1,j,n)
  • 思路 2:
    这道题作为 2sum 的延伸,当然我们的第一想法应该是上面那么复杂(由于没有系统地训练,这两道题时间间隔比较大)。联系 2sum,我们可以很容易想到使用哈希表,这次哈希表记录的不是数字的索引,而是数字出现的次数,或者说数字可以使用的次数。第一个数字,我们遍历整个数组,同时把选中为第一个数字的哈希值-1.第二个数字,遍历整个数组,需要满足哈希值 >0,把选中的数字的哈希值-1.第三个数字,查找哈希表中满足 0-a-b,且哈希值 >0 的数字。这样复杂度可以降低到(n*n)。 由于没有剪枝,所有两重循环是实打实的。
    这里有个奇怪的问题,这份代码提交报了超时,但是超时的用例,使用 leetcode 的测试功能(最近加入的新功能),却能正确得到结果,且时间平均在 80ms,比思路 1 快了 10 倍。

  • 代码:

    class Solution: # @param {integer[]} nums # @return {integer[][]} def threeSum(self, nums): dic={} result=[] for n in nums: if n not in dic:dic[n]=1 else: dic[n]+=1 for a in nums: dic[a]-=1 for b in nums: if dic[b]>0: dic[b]-=1 if 0-a-b in dic and dic[0-a-b]>0 and sorted([a,b,0-a-b]) not in result: result.append(sorted([a,b,0-a-b])) dic[b]+=1 dic[a]+=1 return result

##16.3Sum Closest

  • 难度:Medium

  • 题目大意:
    给定一个整数数组,求 a,b,c 满足 a+b+c 最接近 target。假设有且仅有 1 个解。

  • 思路:
    这道题的思路就和 3Sum 比较接近了,遍历前 2 个数字,但是求第三个数字时,需要对二分查找进行修改,在查找不到时返回和该数最接近的数字。

  • 代码:

    class Solution: # @param {integer[]} nums # @param {integer} target # @return {integer} def threeSumClosest(self, nums, target): sumClosest = 2**32-1 nums.sort() for firstn in range(len(nums)-2): for secondn in range(firstn+1,len(nums)-1): thirdn = self.binarySearch(nums[secondn+1::],0,len(nums[secondn+1::])-1,target-(nums[firstn]+nums[secondn])) stmp = nums[firstn]+nums[secondn]+nums[secondn+1::][thirdn] if stmp == target: return target else: if abs(stmp-target)<abs(sumClosest-target): sumClosest = stmp return sumClosest #binary search #if no such num return the nearlyst def binarySearch(self,nums,i,j,n): if n<nums[i]: if i == 0:return i else: if abs(nums[i]-n)<abs(nums[i-1]-n):return i else:return i-1 if n>nums[j]: if j==len(nums)-1:return j else: if abs(nums[j]-n)<abs(nums[j+1]-n):return j else:return j+1 if i>j: if abs(nums[i]-n)<abs(nums[j]-n):return i else:return j mid = (i+j)//2 if n == nums[mid]:return mid elif n < nums[mid]: return self.binarySearch(nums,i,mid-1,n) else: return self.binarySearch(nums,mid+1,j,n)

##18.4Sum

  • 难度:Medium

  • 题目大意:
    给定整数数组,求出所有 a,b,c,d,满足 a+b+c+d=target。要求元组中升序排列,元组不重复。

  • 思路:
    若按照 2Sum 和 4Sum 的思路,用 3 重循环遍历前 3 个数,再找到满足要求的第 4 个数,肯定是会超时的(基本上在 OJ 中 3 重循环就肯定会超时了),而且剪枝几乎不可能实现,4 个数可能出现的情况太多。
    因此另寻出路:把 4Sum 变成 2 个 2Sum 问题。建立一个哈希表,用于记录{两数之和:[[索引 a,索引 b],...],...},记录索引有一个好处就是可以解决重复数字的问题。遍历 a 和 b,在哈希表中查找 target-a-b,注意排除 1 个数字使用多次的情况。把新的 a+b,加入哈希表中。如此这般时间复杂度仅有(n*n)。

  • 代码:

    class Solution: # @param {integer[]} nums # @param {integer} target # @return {integer[][]} def fourSum(self, nums, target): result = [] sumdir = {} if len(nums)<4: return result nums.sort() for i in range(len(nums)-1): for j in range(i+1,len(nums)): sumlist = sumdir.get(target - (nums[i]+nums[j])) if sumlist: for na,nb in sumlist: if i not in(na,nb) and j not in(na,nb): tmp = sorted([nums[i],nums[j],nums[na],nums[nb]]) if tmp not in result: result.append(tmp) if not sumdir.get(nums[i]+nums[j]): sumdir[nums[i]+nums[j]] = [] sumdir[nums[i]+nums[j]].append([i,j]) return result

  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 2 关注
  • nums
    1 引用
  • return
    2 引用

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖 • 1 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 758 关注
  • Visio
    1 引用 • 2 回帖 • 2 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 441 关注
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    172 引用 • 516 回帖 • 1 关注
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 668 关注
  • OneDrive
    2 引用 • 4 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 701 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 176 关注
  • Outlook
    1 引用 • 5 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 55 关注
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1441 引用 • 10068 回帖 • 494 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 29 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 679 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 132 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    298 引用 • 763 回帖 • 1 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    181 引用 • 821 回帖
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 391 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 25 关注
  • OpenCV
    15 引用 • 36 回帖 • 2 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 100 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 160 关注