Overview
383. Ransom Note
Solution:
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
src = sorted(ransomNote)
dst = sorted(magazine)
idx = 0
for i in src:
try:
j = dst[idx]
while j < i:
idx += 1
j = dst[idx]
except IndexError:
return False
if j == i:
idx += 1
continue
else:
return False
return True
387. First Unique Character in a String
Solution:
第一个思路,排序后查找,再在原字符串中查找。
class Solution:
def firstUniqChar(self, s: str) -> int:
if len(s) == 0:
return -1
if len(s) == 1:
return 0
dst = sorted(s)
founds = set()
key = dst[0]
if key != dst[1]:
founds.add(key)
i = 1
while i < len(dst)-1:
if dst[i] != dst[i+1] and dst[i] != dst[i-1]:
founds.add(dst[i])
i += 1
if dst[-1] != dst[-2]:
founds.add(dst[-1])
if founds:
for i, val in enumerate(s):
if val in founds:
return i
return -1
使用字典,遍历两次 O ( n ) O(n) O(n) 复杂度
from collections import defaultdict
class Solution:
def firstUniqChar(self, s: str) -> int:
d = defaultdict(int)
for i in s:
d[i] += 1
for i, v in enumerate(s):
if d[v] == 1:
return i
return -1
第一次提交使用排序的思路解决,比较耗时。
第二次就是使用字典,应该来说算是可以接受。
可以在遍历的时候,字典的值为 (times, place)
元组,这样就能遍历一次就可以获得结果。
(第二次遍历字典的所有 key,找出 times 为 1,place 最小的值,所有 key 只有 26 个(字母),所以比较省时间)。
Leetcode 提供的 Solution 方法? – n/a
出现频率问题
451. Sort Characters By Frequency
Solution:
from collections import defaultdict
class Solution:
def frequencySort(self, s: str) -> str:
d = defaultdict(int)
for i in s:
d[i] += 1
_t = sorted(d.items(), key=lambda _: _[1], reverse=True)
ret = []
for k, v in _t:
ret.append(k*v)
return "".join(ret)
347. Top K Frequent Elements
Solution:
from collections import defaultdict
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
d = defaultdict(int)
for i in nums:
d[i] += 1
_t = sorted(d.items(), key=lambda _: _[1], reverse=True)
ret = []
for i in range(k): # k times
ret.append(_t[i][0])
return ret
821. Shortest Distance to a Character
Solution:
class Solution:
def shortestToChar(self, S: str, C: str) -> List[int]:
if len(S) == 1: # guaranteed to be in string S.
return [0]
if S[0] != C:
left = -1
else:
left = 0
_l = []
for i in range(1, len(S)):
if S[i] == C:
right = i
_l.append((left, right))
left = right
if S[-1] != C:
_l.append((left, -1))
ret = []
cnt = 0
left, right = _l[cnt]
for i in range(len(S)):
if right != -1 and i > right:
left, right = _l[cnt + 1]
cnt += 1
if left == -1:
dist_left = float('inf')
else:
dist_left = i - left
if right == -1:
dist_right = float('inf')
else:
dist_right = right - i
ret.append(min(dist_left, dist_right))
return ret
844. Backspace String Compare - 自定义 [Backspace] 键协议
Solution:
class Solution:
def backspaceCompare(self, S: str, T: str) -> bool:
i = -1
j = -1
cnt = 0
try:
while True:
if S[i] != "#" and T[j] != "#":
if S[i] != T[j]:
return False
else:
i -= 1
j -= 1
elif S[i] == "#":
cnt = 1
i -= 1
while cnt:
while S[i] == "#":
cnt += 1
i -= 1
if S[i] != "#":
cnt -= 1
i -= 1
else:
cnt = 1
j -= 1
while cnt:
while T[j] == "#":
cnt += 1
j -= 1
if T[j] != "#":
cnt -= 1
j -= 1
except IndexError:
if abs(i) > len(S): # S IndexError
return self.str_is_equl_empty(T, j)
elif abs(j) > len(T):
return self.str_is_equl_empty(S, i)
else:
return True
def str_is_equl_empty(self, s, n):
# note: n is negative
cnt = 0
while True:
try:
c = s[n]
if c != "#" and cnt == 0:
return False
elif c != "#":
cnt -= 1
n -= 1
else:
cnt += 1
n -= 1
except IndexError:
return True
return False
这样的写法容易出错,确实不出所料,测试的时候少测试了以下这种情况:
"bxj##tw"
"bxo#j##tw"
导致提交的时候错误了一次。
写这种程序有更好的方式吗?不知道!
如果不关心多遍历一次的化,先 generate 出来不含 “#” 的最后的真正输入字符串,然后再比较。这样或者代码看上去更友好一些。
929. Unique Email Addresses
Every email consists of a local name and a domain name, separated by the @ sign.
For example, in alice@leetcode.com
, alice
is the local name, and leetcode.com
is the domain name.
Besides lowercase letters, these emails may contain '.'
s or '+'
s.
If you add periods ('.'
) between some characters in the local name part of an email address, mail sent there will be forwarded to the same address without dots in the local name. For example, "alice.z@leetcode.com"
and "alicez@leetcode.com"
forward to the same email address. (Note that this rule does not apply for domain names.)
If you add a plus ('+'
) in the local name, everything after the first plus sign will be ignored. This allows certain emails to be filtered, for example m.y+name@email.com
will be forwarded to my@email.com
. (Again, this rule does not apply for domain names.)
It is possible to use both of these rules at the same time.
Given a list of emails
, we send one email to each address in the list. How many different addresses actually receive mails?
Example 1:
Input:
["test.email+alex@leetcode.com","test.e.mail+bob.cathy@leetcode.com","testemail+david@lee.tcode.com"]
Output:2
Explanation: "testemail@leetcode.com" and "testemail@lee.tcode.com" actually receive mails
Solution:
import re
class Solution:
def get_real_email(self, emails):
ret = []
for email in emails:
s, domain = email.split("@")
l = re.findall(r"(\w+\.?)", s.split("+")[0])
l = [s.rstrip(".") for s in l]
local_name = ''.join(l)
ret.append(local_name + "@" + domain)
return ret
def numUniqueEmails(self, emails: List[str]) -> int:
if not emails:
return 0
return len(set(self.get_real_email(emails)))