【Leetcode】字符串问题整理笔记



383. Ransom Note

n/a

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

n/a

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

n/a
第一次提交使用排序的思路解决,比较耗时。
第二次就是使用字典,应该来说算是可以接受。

可以在遍历的时候,字典的值为 (times, place) 元组,这样就能遍历一次就可以获得结果。
(第二次遍历字典的所有 key,找出 times 为 1,place 最小的值,所有 key 只有 26 个(字母),所以比较省时间)。

Leetcode 提供的 Solution 方法? – n/a



出现频率问题

451. Sort Characters By Frequency

n/a
n/a

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)

n/a



347. Top K Frequent Elements

n/a

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

n/a



821. Shortest Distance to a Character

n/a

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

n/a



844. Backspace String Compare - 自定义 [Backspace] 键协议

n/a
n/a
n/a

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 出来不含 “#” 的最后的真正输入字符串,然后再比较。这样或者代码看上去更友好一些。

n/a



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

n/a
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)))

n/a



Reference



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值