383. Ransom Note
Description
Given two strings ranosmNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise.
Each letter in magazine can only be used once in ransomNote.
Example 1:
- Input: ransomNote = “a”, magazine = “b”
- Output: false
Example 2:
- Input: ransomNote = “aa”, magazine = “ab”
- Output: false
Example 3:
- Input: ransomNote = “aa”, magazine = “aab”
- Output: true
Constraints:
- 1 <= ransomNote.length, magazine.length <= 105
ransomNoteandmagazineconsist of lowercase English letters.
Submitted Code
class Solution(object):
def canConstruct(self, ransomNote, magazine):
"""
:type ransomNote: str
:type magazine: str
:rtype: bool
"""
if len(ransomNote) > len(magazine): # ransomNote가 magazine보다 길다면 바로 False
return False
count = {}
for l in ransomNote:
count[l] = count.get(l, 0) + 1
for l in magazine:
if l in count and count[l] != 0:
count[l] -= 1
# 딕셔너리의 각 값이 0인지 확인하고 모두 0일 때만 True
return True if all(v == 0 for v in count.values()) else False
Runtime: 19 ms | Beats 88.90%
Memory: 12.85 MB | Beats 15.54%
해시 테이블을 사용했다.
Other Solutions
1st
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
maga_hash = {}
for c in magazine:
maga_hash[c] = 1 + maga_hash.get(c, 0)
for c in ransomNote:
if c not in maga_hash or maga_hash[c] <= 0:
return False
maga_hash[c] -= 1
return True
time complexity: 𝑂(𝑛+𝑚)
space complexity: 𝑂(26 → 1)
ransomNote 대신 magazine의 원소와 출현 횟수를 해시 테이블에 저장하는 방법이 훨씬 더 깔끔한 것 같다.
2nd
from collections import Counter
class Solution(object):
def canConstruct(self, ransomNote, magazine):
st1, st2 = Counter(ransomNote), Counter(magazine)
if st1 & st2 == st1: # 교집합이 ransomNote와 동일할 경우 True
return True
return False
파이썬의 내장 모듈 collections.Counter은 각 문자의 출현 횟수를 자동으로 세어주는 딕셔너리이다. 또 Counter 객체끼리는 & 연산이 가능하기 때문에 편리하다.