LeetCode攀登之旅(2)

  • 2019 年 10 月 5 日
  • 筆記

LeetCode攀登之旅(2)

0.本节思想

1.两数之和

2.无重复字符的最长子串

3.作者的话

0.本节思想

数据结构:哈希表 形式:(key,value)

1.两数之和

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:

给定 nums = [2, 7, 11, 15], target = 9  因为 nums[0] + nums[1] = 2 + 7 = 9  所以返回 [0, 1]

暴力解决本题就是双重for循环,此法效率太低,这里采用O(n)的时间复杂度算法,哈希思想算法。

首先给定nums=[2,7,11,15],利用这个数组去构造key,value。

nums[i]即为里面的value,key即为index。

那如果换成nums[i]为value,key为index呢,如果采用这个方法,在去遍历的时候,很不方便,因为我们是直接找对应的差值是否在这个哈希表中,如果nums[i]换成了value,则直接查找不到了!

以下给出Python实现代码:

  • 新建一个hash表
  • 通过enumerate循环可以直接获取key与value
  • 然后根据key得到其中一个数,再根据此数从哈希表中寻找另外一个数
  • 一开始哈希表为空,另外一个数肯定不存在哈希表中,那么我们每次给哈希表赋值,key为number,value为index
  • 最终返回的两个数的顺序为哈希表中的index与当前遍历的index。或者直接sorted排序即可!

【哈希code】

class Solution:      def twoSum(self,nums,target):          nums_hash = {}          for index,number in enumerate(nums):              one_num = nums[index]              other_num = target-one_num              if other_num in nums_hash:                  return [nums_hash[other_num],index]              nums_hash[number] = index          return []

手动推演:

nums = [2,6,8,9] target=10

当one_num = 2(index=0)时,other_num=8,此时这个数不在哈希表中,先将当前数加入哈希表中,得到nums_hash = {2:0}

当one_num=6(index=1)时候,other_num=4,继续重复上述操作,得到nums_hash={2:0,6:1}

当one_num=8(index=2)时,other_num=2,此时此数在哈希表中,直接返回[nums_hash[other_num],index] ,循环结束,退出程序。

2.无重复字符的最长子串

给定一个字符串,找出不含有重复字符的最长子串的长度。 示例 1:

输入: "abcabcbb"  输出: 3  解释: 无重复字符的最长子串是 "abc",其长度为 3。

示例 2:

输入: "bbbbb"  输出: 1  解释: 无重复字符的最长子串是 "b",其长度为 1。

示例 3:

输入: "pwwkew"  输出: 3  解释: 无重复字符的最长子串是 "wke",其长度为 3。       请注意,答案必须是一个子串,"pwke" 是一个子序列 而不是子串。

暴力解法: 【解题思想】 首先想到遍历整个字符,然后对遍历到的每个字符后的字符处理,即判断它是否是重复元素,这个判别可以通过list/dict/str解决,如果检查的字符不在这个判别list/dict/str里面,则加入进去,并记录本次长度,在最外面定义一个最大长度标记,将每次的长度与最大长度对比,取最大即为最终结果! 【暴力code】

def lengthOfLongestSubstring(self, s):      """      :type s: str      :rtype: int      """      MaxLength = 0      for i in range(len(s)):          st = ''          count = 0          for j in s[i:]:              if j not in st:                  st += j                  count += 1                  if (MaxLength<count):                      MaxLength=count              else:                  break      return MaxLength

手动推演:

给定字符s="pwwkew",首先得到s的总长6,接着对其做6次循环。  当i=0时:count=0,此时的j的范围为"pwwkew"  内部过程如下:  st='p' count=1 MaxLength=1 st='pw' count=2 MaxLength=2  w in st中,直接退出本次循环  跳至外部循环如下:  当i=1时:count=0,此时的j的范围为"wwkew"  内部过程如下:  st='w' count=1 MaxLength=1  w in st中,直接退出本次循环  跳至外部循环如下:  当i=2时:count=0,此时的j的范围为"wkew"  内部过程如下:  st='w' count=1 MaxLength=2 st='wk' count=2 MaxLength=2  st='wke' count=3 MaxLength=3  w in st中,直接退出本次循环  跳至外部循环如下:  当i=3、4、5,依此重复上述过程,最终返回MaxLength

哈希解法: 注意到上述的手动推演了?可以看到在下次查找重复元素时,实际上白做了这么一段过程,比如:i=0可直接跳到i=2情况下,那么此时效率肯定会高很多,也就是当i=1时是没有用的,因为去掉一个元素后,不可能比之前的元素长度还长! 以下分别为i=0,i=1,i=2的情况

p w w k e w  i      j  hash_str = pw 
p w w k e w    i      j  hash_str = w 
p w w k e w      i      j  hash_str = w 

【解题思想】 于是乎新思想出来了,我们跳过i=1的过程,直接从两个相等情况入手,而存储的j位字符为上述的哈希表,没错,我们仿照上述两数之和的哈希思想去解决这个问题,会变得非常简单,从原先的O(n^2)变为现在的O(n)复杂度! 这里有一点注意,最大长度是根据index与start位置变化,所以这里是index-start+1

实质:例如:字符串为"pswkwabc",原先按照暴力解法,直接循环每一个元素,  那么用哈希跟跳过重复元素解决则为,从  p     s w k w a b c  start  直接指向了重复元素w的后一个元素k,刚好跳过重复元素  p s w   k   w a b c        start

【哈希code】 看下面代码跟上述两数之和,及其相似,一个是找到元素就退出,一个是等对比完,找出最大长度,才退出!

def lengthOfLongestSubstring(self, s):      """      :type s: str      :rtype: int      """      start = MaxLength = 0      hash_str = {}      for index,char in enumerate(s):          if char in hash_str and start<=hash_str[char]:              start = hash_str[char]+1          else:              if(MaxLength<(index-start+1)):                  MaxLength=index-start+1          hash_str[char] = index        return MaxLength

手动推演: 以pwwkew为例:

-------------------------  start = MaxLength = 0   hash_str = {}  index = 0, char= 'p' 此时char不在hash_str中,进入else里面  MaxLength=1 退出判断, hash_str={'p':0}  -------------------------  index = 1, char= 'w' 此时char不在hash_str中,进入else里面  MaxLength=2 退出判断, hash_str={'p':0,'w':1}  -------------------------  index = 2, char= 'w' 此时char在hash_str中,并且start=0<hash_str['w']=1,进入if里面  start=2 退出判断, hash_str={'p':0,'w':1,'w':2}  -------------------------  index = 3, char= 'k' 此时char不在hash_str中,进入else里面  MaxLength=2 退出判断, hash_str={'p':0,'w':1,'w':2,'k':3}  -------------------------  index = 4, char= 'e' 此时char不在hash_str中,进入else里面  MaxLength=3 退出判断, hash_str={'p':0,'w':1,'w':2,'k':3}  -------------------------  index = 4, char= 'e' 此时char在hash_str中,并且start=2=hash_str['w']=2,进入if里面  start=3 退出判断, hash_str={'p':0,'w':1,'w':2,'k':3,'w':4}  -------------------------  return MaxLength=3

【效率对比】

暴力解法图

哈希解法图

3.作者的话

最后,您如果觉得本公众号对您有帮助,欢迎您多多支持,转发,谢谢! 更多刷题,请关注本公众号算法系列!