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

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

##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 回帖 • 3 关注
  • nums
    1 引用
  • return
    2 引用

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    108 引用 • 54 回帖
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 55 关注
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 1 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 7 关注
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 71 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 417 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 11 关注
  • 大数据

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

    89 引用 • 113 回帖
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    16 引用 • 53 回帖 • 124 关注
  • RYMCU

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

    4 引用 • 6 回帖 • 40 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    180 引用 • 447 回帖 • 1 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    82 引用 • 122 回帖 • 619 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 606 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    10 引用 • 54 回帖 • 126 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    163 引用 • 1450 回帖
  • 电影

    这是一个不能说的秘密。

    120 引用 • 597 回帖
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 10 关注
  • 倾城之链
    23 引用 • 66 回帖 • 100 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    21 引用 • 140 回帖 • 27 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 609 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 350 关注
  • ActiveMQ

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

    19 引用 • 13 回帖 • 626 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    116 引用 • 99 回帖 • 267 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖 • 1 关注