【Leetcode】刷题之路2(python)
哈希映射類題目(簡單題小試牛刀啦bhn)
- 242.有效的字母異位詞
- 349.兩個數組的交集
- 1002.查找常用字符
- 202.快樂數
- 383.贖金信
242. 有效的字母異位詞
用python的Counter類太絕了!!!
一行代碼解決問題,這道題實際上就是比較兩個字符串的每個字母數是不是一樣。
在刷題之路1的最后我列出了collections模塊的幾個字典的子類
Counter:字典的子類,提供了哈希對象的計數功能
class Solution:def isAnagram(self, s: str, t: str) -> bool:return Counter(s)==Counter(t)
349. 兩個數組的交集
思路:
1.先把nums1和nums2轉為集合
2.兩集合求交集
3.再把交集轉化為list
class Solution(object):def intersection(self, nums1, nums2):return list(set(nums1) & set(nums2))
1002. 查找常用字符
給你一個字符串數組 words ,請你找出所有在 words 的每個字符串中都出現的共用字符( 包括重復字符),并以數組形式返回。你可以按任意順序 返回答案。
題解
利用python內置模塊一行代碼解決問題:求每個計數器的交集即可
解釋:
-
Counter類
Counter類基于dict字典類,可使用dict的方法,其實例可以進行 與 或 非 異或 運算。 -
map
map(function, iterable, …):會根據提供的函數對指定序列做映射。第一個參數 function 以參數序列中的每一個元素調用 function 函數,返回包含每次 function 函數返回值的新列表。 -
reduce
reduce(function, iterable[, initializer]):對迭代器內進行兩個元素操作并傳遞。
求每個計數器的交集即可,而這個交集必須與其后的交集傳遞下去,因此 reduce 函數滿足。即這里求兩個 Counter 計數器的交集操作,然后作為參數 x 傳遞到下一個去和 iterable 下一個計數器取交集。由于 reduce 最后運算得到的是 Counter 對象,因此取出元素 Counter.elements() 是迭代器,因而 list 創建列表。
class Solution:def commonChars(self, A: List[str]) -> List[str]:return reduce(lambda x, y: x&y, map(Counter, A)).elements()# 使用 lambda 匿名函數
代碼詳細展開如下:
class Solution:def commonChars(self, A: List[str]) -> List[str]:from collections import Counterans = Counter(A[0])for i in A[1:]:ans &= Counter(i)return list(ans.elements())
202. 快樂數
編寫一個算法來判斷一個數 n 是不是快樂數。
「快樂數」定義為:對于一個正整數,每一次將該數替換為它每個位置上的數字的平方和。然后重復這個過程直到這個數變為 1,也可能是 無限循環 但始終變不到 1。如果 可以變為 1,那么這個數就是快樂數。
題解
方法一:哈希集合檢測循環
我們可以先舉幾個例子,找出快樂數的規律,發現有三種可能性:
- 最終會得到 1。
- 最終會進入一個循環。
- 值會越來越大,最后接近無窮大。(但經過驗證不存在)
所以要么是快樂數,要么會進入一個循環。
思路:
算法分為兩部分,我們需要設計和編寫代碼。
- 給一個數字 nn,它的下一個數字是什么?
- 按照一系列的數字來判斷我們是否進入了一個循環。
實現:
第 1 部分我們按照題目的要求做數位分離,求平方和。
第 2 部分可以使用哈希集合完成。每次生成鏈中的下一個數字時,我們都會檢查它是否已經在哈希集合中。
- 如果它不在哈希集合中,我們應該添加它。
- 如果它在哈希集合中,這意味著我們處于一個循環中,因此直接返回 false。
(注!我們使用哈希集合而不是向量、列表或數組的原因是因為我們反復檢查其中是否存在某數字。檢查數字是否在哈希集合中需要 O(1) 的時間,而對于其他數據結構,則需要 O(n) 的時間。選擇正確的數據結構是解決這些問題的關鍵部分。)
函數divmod(dividend, divisor)是Python的內置函數,它可以把除數和余數運算結果結合起來,返回一個包含商和余數的元組(a / b, a % b)。
def isHappy(self, n: int) -> bool:def get_next(n):total_sum = 0while n > 0:n, digit = divmod(n, 10)total_sum += digit ** 2return total_sumseen = set()while n != 1 and n not in seen:seen.add(n)n = get_next(n)return n == 1
復雜度分析
時間復雜度:時間復雜度:O(243?3+logn+loglogn+logloglogn)… = O(logn)。
空間復雜度:O(\log n)O(logn)。
方法二:快慢指針法
通過反復調用 getNext(n) 得到的鏈是一個隱式的鏈表。隱式意味著我們沒有實際的鏈表節點和指針,但數據仍然形成鏈表結構。起始數字是鏈表的頭 “節點”,鏈中的所有其他數字都是節點。next 指針是通過調用 getNext(n) 函數獲得。
意識到我們實際有個鏈表,那么這個問題就可以轉換為檢測一個鏈表是否有環。因此我們在這里可以使用弗洛伊德循環查找算法。
這個算法是兩個奔跑選手,一個跑的快,一個跑得慢。在龜兔賽跑的寓言中,跑的慢的稱為 “烏龜”,跑得快的稱為 “兔子”。如果有環的話,不管烏龜和兔子在循環中從哪里開始,它們最終都會相遇。這是因為兔子每走一步就向烏龜靠近一個節點(在它們的移動方向上)。
算法
我們不是只跟蹤鏈表中的一個值,而是跟蹤兩個值,稱為快跑者和慢跑者。在算法的每一步中,慢速在鏈表中前進 1 個節點,快跑者前進 2 個節點(對 getNext(n) 函數的嵌套調用)。
- 如果 n 是一個快樂數,即沒有循環,那么快跑者最終會比慢跑者先到達數字 1。
- 如果 n 不是一個快樂的數字,那么最終快跑者和慢跑者將在同一個數字上相遇。
def isHappy(self, n: int) -> bool: def get_next(number):total_sum = 0while number > 0:number, digit = divmod(number, 10)total_sum += digit ** 2return total_sumslow_runner = nfast_runner = get_next(n)while fast_runner != 1 and slow_runner != fast_runner:slow_runner = get_next(slow_runner)fast_runner = get_next(get_next(fast_runner))return fast_runner == 1
時間復雜度:O(logn)
空間復雜度:O(1),對于這種方法,我們不需要哈希集來檢測循環。
383. 贖金信
為了不在贖金信中暴露字跡,從雜志上搜索各個需要的字母,組成單詞來表達意思。
給你一個贖金信 (ransomNote) 字符串和一個雜志(magazine)字符串,判斷 ransomNote 能不能由 magazines 里面的字符構成。如果可以構成,返回 true ;否則返回 false 。
magazine 中的每個字符只能在 ransomNote 中使用一次。
題解
使用Counter類的交集操作,獲得交集,判斷兩者交集是否等于ransomNote,是則滿足,否則不滿足。(Counter yyds!)
class Solution:def canConstruct(self, ransomNote: str, magazine: str) -> bool:a = Counter(ransomNote) b = Counter(magazine)return (a & b) == a
用內存換時間!!!
總結
python的哈希類題目,可以多多考慮collections模塊下的counter子類,counter提供了哈希對象的計數功能
總結
以上是生活随笔為你收集整理的【Leetcode】刷题之路2(python)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个qq个性网网名两个字。
- 下一篇: 成语接龙下笑成章下一句是什么呢?