![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SZ0E2MwAjY4I2MhVmMjZTNiFjMwY2Y5EGNmZmMlFDZ38CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
LeetCode 中 一道題目如下
給定一個僅包含大小寫字母和空格 ' ' 的字元串 s,傳回其最後一個單詞的長度。 如果字元串從左向右滾動顯示,那麼最後一個單詞就是最後出現的單詞。 如果不存在最後一個單詞,請傳回 0 。 說明:一個單詞是指僅由字母組成、不包含任何空格字元的 最大子字元串。 示例: 輸入: "Hello World" 輸出: 5 原題連結: https://leetcode-cn.com/problems/length-of-last-word |
終于刷到一條不看答案就能輕松解出來的題目,更重要的是學習到了幾種删除清單中元素的方法,值得做一下筆記
解題思路
先說下我的思路:題目要求給一個字元串s,s僅包含字母和空格字元,要求傳回最後一個單詞的長度,考慮如下幾點
- 如果s是空字元,即s="",此時應該傳回0;
- 如果s隻包含空格字元,即s=" ",此時也應該傳回0;
- 如果s既包含字母也包含空格(或者隻包含字母),可以通過split()函數,用一個空格字元切割,這樣就可以得到一個清單,這個清單隻由連續的字母和空字元組成,然後把清單中的所有空字元删除,最後把清單中的最後一項的長度傳回即可;
是以現在的問題就轉化為:如何删除一個清單中的特定元素,這裡的話,就是删除清單中的空字元,即""
解決方法
方法1: 借助一個臨時清單,把非空元素提取到臨時清單中,然後取出臨時清單最後一項,傳回其長度即可 這是最笨的方法,實際運作時也是最耗時的方法
class Solution(object): def lengthOfLastWord(self, s): """ :type s: str :rtype: int """ if s.isspace(): # 判斷s是否隻由空格字元組成,如s==" " return 0 elif s == "": # 判斷s是否為空字元串,如s=="" return 0 else: # 如果s不為空,且不全是由空格組成 temp = s.split(" ") # 通過split方法,用一個空格字元将字元串s進行切割,可以得到由單詞和空字元串組成的清單,将清單賦給temp new = [] # 定義一個空清單,作為中間變量 for t in temp: # 周遊temp,把非空元素提取到new中,最後把new的最後一項的長度傳回即可 if t != "": new.append(t) return len(new[-1])
在說方法2之前,說一個錯誤的方法 : 使用for循環,正向周遊清單,删除其中的空字元,如下
s = ["","","a", "a", "a","","",""]for i in range(0,len(s)): if s[i] == "": del s[i]print(s)
運作上述代碼,會報錯
原因是當遇到空字元時,把空字元删掉後,清單長度變小了,但是循環周遊時,還是按照最初的長度周遊,導緻溢出;
另外這樣寫還存在一個弊端:可能會漏删某些空字元,原因是當删掉前面的空字元後,後面的元素依次向前移動,導緻索引與原先對應的值發生變化,如下
b = ["","","a", "a", "a","","",""]for i in range(0,len(b)): if i >= len(b): # 加一個判斷,當i大于清單長度時,跳出循環,避免報錯 break if b[i] == "": del b[i]print(b)
是以我們在解決這個問題前,不能用for循環來正向周遊清單
方法2:
使用while循環 因為for循環無法達到目的,是以考慮使用while循環,如下
class Solution(object): def lengthOfLastWord(self, s): """ :type s: str :rtype: int """ if s.isspace(): # 判斷s是否隻由空格字元組成,如s==" " return 0 elif s == "": # 判斷s是否為空字元串,如s=="" return 0 else: # 如果s不為空,且不全是由空格組成 temp = s.split(" ") # 通過split方法,用一個空格字元将字元串s進行切割,可以得到由單詞和空字元串組成的清單,将清單賦給temp i = 0 # 設定初始指針,定為0 while i < len(temp): # 使用while循環,當指針i的值小于清單temp的長度時,則一直循環 if temp[i] == "": # 從索引0開始,如果temp[i]為空 del temp[i] # 則删除該索引對應的值,也就是删除temp[i] i -=1 # 删除之後,由于清單整體長度變小了1位(也就是後面的元素都往前提了一位),是以索引i需要減1,以便下次周遊時不丢掉挨着的元素 i += 1 # 判斷完索引i後,給索引自增1,進行下一輪判斷 return len(temp[-1]) # temp所有元素周遊完成後,就剔除了所有空字元串,取出最後一項的長度傳回即可
方法3:
for循環倒序删除空字元串 剛才說了使用for循環時,正向周遊會導緻溢出或者結果出錯,但是從後向前周遊是可以的
class Solution(object): def lengthOfLastWord(self, s): """ 倒序循環删除空字元串 :type s: str :rtype: int """ if s.isspace(): # 判斷s是否隻由空格字元組成,如s==" " return 0 elif s == "": # 判斷s是否為空字元串,如s=="" return 0 else: # 如果s不為空,且不全是由空格組成 temp = s.split(" ") # 通過split方法,用一個空格字元将字元串s進行切割,可以得到由單詞和空字元串組成的清單,将清單賦給temp for i in range(len(temp)-1, -1, -1): # 倒序循環删除空字元串 if temp[i] == "": del temp[i] return len(temp[-1])
方法4:
拷貝原清單,然後周遊拷貝的清單來找出空字元,最後再原清單中删除空字元
class Solution(object): def lengthOfLastWord_3(self, s): """ :type s: str :rtype: int """ if s.isspace(): # 判斷s是否隻由空格字元組成,如s==" ",用isspace()函數判斷 return 0 elif s == "": # 判斷s是否為空字元串,如s=="" return 0 else: # 如果s不為空,且不全是由空格組成 temp = s.split(" ") # 通過split方法,用一個空格字元将字元串s進行切割,可以得到由單詞和空字元串組成的清單,将清單賦給temp for i in temp[:]: # temp[:]是對原始的temp的一個拷貝,是一個新的list,是以,我們周遊新的list,而删除原始的list中的元素 if i == "": temp.remove(i) return len(temp[-1])
這樣了解一下:假如有一個清單s = [1,1,2,3,4,4,3,1],現在要把裡面的1都删掉
我們先拷貝s,得到一個新清單(注意不能用一個變量直接等于s,如a=s,其實a和s都指向同一個清單,本質還是一個),新清單的元素與原清單完全相同 然後周遊新清單,當遇到某個元素的值為1時,就在原清單中把這個元素删掉(使用清單的remove方法删除),因為remove在删除元素時,隻會删掉遇到的第一個目标元素,是以我們繼續周遊新清單,如果再遇到1,就繼續在原清單中删除
最終周遊完新清單,也就會在原清單中把所有1都删掉了
上述代碼中的 temp[:] 是拷貝原清單得到新清單的一個方法,也可以通過如下方法複制得到一個新清單
1 >>> new_temp = temp[:]2 >>> new_temp = list(temp)3 >>> new_temp = temp*14 >>> import copy >>> new_temp = copy.copy(temp)
關于原地删除清單中特定元素的方法,參考了如下文章:
https://www.jb51.net/article/169070.htm
關于拷貝清單,參考了如下文章:
https://www.cnblogs.com/ifantastic/p/3811145.html
喜歡記得來一個