Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.
Each letter in the magazine string can only be used once in your ransom note.
Note:
You may assume that both strings contain only lowercase letters.
canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
思路:
- 第一反应是依次遍历ransomNote,如果其中的元素都在magazine,则返回True,否则返回False,这个应该可以解决这个问题,不过效率肯定不高。由于元素只能用一次,还要考虑删除的问题。
- 使用pop和remove同时处理两个列表,对第一个使用pop(),如果在magazine,则删除之。如果元素不在,则返回False,如果在里面,继续删除。
- 使用collections.Counter(),对于两个Counter的相减,只保留正值的计数。如果每一个value都是正数,则说明magazine可以组成前者。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
class Solution(object):
def canConstruct(self, ransomNote, magazine):
"""
:type ransomNote: str
:type magazine: str
:rtype: bool
"""
ransomNote = list(ransomNote)
magazine = list(magazine)
while ransomNote:
tem = ransomNote.pop()
print tem
if tem not in magazine:
return False
else:
magazine.remove(tem)
return True
def canConstruct2(self, ransomNote, magazine):
import collections
return not collections.Counter(ransomNote) - collections.Counter(magazine)
def canConstruct3(self, ransomNote, magazine):
import collections
c = collections.Counter(magazine)
c.subtract(collections.Counter(ransomNote))
return all(v>=0 for v in c.values())
if __name__ == '__main__':
sol = Solution()
s1 = "aa"
s2 = "aab"
print sol.canConstruct(s1, s2)
print sol.canConstruct2(s1, s2)
print sol.canConstruct3(s1, s2)