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.作者的話

最後,您如果覺得本公眾號對您有幫助,歡迎您多多支持,轉發,謝謝! 更多刷題,請關注本公眾號算法系列!