字符串 696. 计数二进制子串 482. 密钥格式化 242.有效的字母异位词 205. 同构字符串 290. 单词规律

696. 计数二进制子串

  • 给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。
    重复出现的子串要计算它们出现的次数。

示例:

示例 1 :
输入: "00110011"
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
请注意,一些重复出现的子串要计算它们出现的次数。
另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。

示例 2 :
输入: "10101"
输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。

思路1:使用类似寻找回文子串方法

代码实现1:

class Solution:
    def countBinarySubstrings(self, s: str) -> int:
		if not s:
            return 0
        n = len(s)
        ans = 0

        for center in range(2 * n - 1):
            left = center // 2
            right = center % 2 + left
            if left >= 0 and right < n and s[left] == '0' and s[right] == '1':
                while left >= 0 and right < n and s[left] == '0' and s[right] == '1':
                    ans += 1
                    left -= 1
                    right += 1
            elif left >= 0 and right < n and s[left] == '1' and s[right] == '0':
                while left >= 0 and right < n and s[left] == '1' and s[right] == '0':
                    ans += 1
                    left -= 1
                    right += 1

        return ans

思路2:按字符分组

  1. 使用一个group数组,表示字符串中连续重复字符的个数。例如,如果 s=“11000111000000”,则 groups=[2,3,3,6]。
  2. 根据题目,符合要求的子串,必须出现在两个组之间。如果我们有 groups[i] = 2, groups[i+1] = 3,那么它表示 “00111” 或 “11000”。显然,我们可以在此字符串中生成 min(groups[i], groups[i+1]) 个有效的二进制字符串。

算法:
创建上面定义的 groups。s 的第一个元素属于它自己的组。每个元素要么与前一个元素不匹配,从而开始一个大小为 1 的新组;要么匹配,从而使最近一个组的大小增加 1。
然后,我们将取 min(groups[i-1], groups[i]) 的和。

代码实现2:

class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        group = [1]
        ans = 0
        for i in range(1, len(s)):
            if s[i] == s[i-1]:
                group[-1] += 1
            else:
                group.append(1)
        for i in range(1, len(group)):
            ans += min(group[i], group[i-1])

        return ans

思路3:线性扫描

按照思路2,若s=“11000111000000”,则 groups=[2,3,3,6]
我们可以只记住 prev = groups[-2] 和 cur=groups[-1] 来代替 groups。
初始定义pre = 0,cur=1,当二进制字符未改变时,cur+1;发生改变时,取pre和cur的最小值,并累加,再将cur的值赋予pre,cur置1。

代码实现:

class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        ans = 0
        pre, cur = 0, 1
        for i in range(1, len(s)):
        	if s[i-1] = s[i]:
				cur += 1
            else:
                ans += min(pre, cur)
                pre, cur = cur, 1
        # 处理走到最后的情况
        ans += min(pre, cur)
        return ans

482. 密钥格式化

  • 给定一个密钥字符串S,只包含字母,数字以及 ‘-’(破折号)。N 个 ‘-’ 将字符串分成了 N+1 组。给定一个数字 K,重新格式化字符串,除了第一个分组以外,每个分组要包含 K 个字符,第一个分组至少要包含 1 个字符。两个分组之间用 ‘-’(破折号)隔开,并且将所有的小写字母转换为大写字母。
    给定非空字符串 S 和数字 K,按照上面描述的规则进行格式化。

示例:

示例 1:
输入:S = "5F3Z-2e-9-w", K = 4
输出:"5F3Z-2E9W"
解释:字符串 S 被分成了两个部分,每部分 4 个字符;
     注意,两个额外的破折号需要删掉。
     
示例 2:
输入:S = "2-5g-3-J", K = 2
输出:"2-5G-3J"
解释:字符串 S 被分成了 3 个部分,按照前面的规则描述,第一部分的字符可以少于给定的数量,其余部分皆为 2 个字符。
 
提示:
S 的长度不超过 12,000,K 为正整数
S 只包含字母数字(a-z,A-Z,0-9)以及破折号'-'
S 非空

思路:

  1. 用python库函数处理字符串,去掉’-‘并且转大写
  2. 字符串长度对K取余,如果有余数,第一个分组先放余数长度个字符
  3. 每K个字符后放置一个’-’,然后去除原字符串中的K个字符,直到原字符串为空
  4. 最后去掉末尾多余的’-‘

代码实现:

class Solution:
    def licenseKeyFormatting(self, S: str, K: int) -> str:
        s = S.replace('-', '').upper()
        ret = ''
        head = len(s) % K
        if head != 0:
            ret += s[:head] + '-'
            s = s[head:]
        while s:
            ret += s[:K] + '-'
            s = s[K:]

        return ret[:-1]

242. 有效的字母异位词

  • 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词(字符串长度相等、位置不同)。

示例:

示例 1:
输入: s = "anagram", t = "nagaram"
输出: true

示例 2:
输入: s = "rat", t = "car"
输出: false

思路1:排序

  1. 判断两字符串长度是否相等,若不相等,直接返回False。
  2. 通过sorted()方法,查看字符串重新排序后是否相等。
sort 与 sorted 区别:
  • sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
  • list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

思路2:哈希表

  1. 判断两字符串长度是否相等,若不相等,直接返回False。
  2. 遍历s字符串,将每个字符与其出现的次数构成映射关系,存入哈希表。
  3. 遍历t字符串,将每个字符与哈希表的键进行匹配,若匹配到,则将出现次数-1,若匹配不到,设为-1。
  4. 判断匹配后,字符在哈希表中的值是否小于0,若小于零,说明s字符串中无此字符,直接返回False。

代码实现1:

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        hashmap={}
        
        if len(s) != len(t):
            return False

        if sorted(s) == sorted(t):
            return True
        else:
            return False

代码实现2:

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        hashmap={}
        
        if len(s) != len(t):
            return False

        for c in s:
            hashmap[c] = hashmap.get(c, 0) + 1
        
        for i in t:
            hashmap[i] = hashmap.get(i, 0) - 1
            if hashmap[i]<0:
                return False
        
        return True

205. 同构字符串

  • 给定两个字符串 s 和 t,判断它们是否是同构的。
    如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
    所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

示例:

示例 1:
输入: s = "egg", t = "add"
输出: true

示例 2:
输入: s = "foo", t = "bar"
输出: false

示例 3:
输入: s = "paper", t = "title"
输出: true

思路1:哈希表

建立 s − > t s->t s>t t − > s t->s t>s 之间的映射关系。
遍历s,哈希表中没有当前字符的映射,则添加映射进哈希表,如果映射已经存在,判断当前映射关系是否正确。
遍历t,重复上述操作。

代码实现1:

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        hashmap1 = {}
        hashmap2 = {}
        n = len(s)
        # s-->t
        for i in range(n):
            if s[i] not in hashmap1:
                # 如果哈希表中没有当前字符的映射,则添加映射进哈希表
                hashmap1[s[i]] = t[i]
            elif hashmap1.get(s[i]) != t[i]:
                # 如果映射已经存在,但原有映射与当前不同,返回False
                return False
        # t-->s
        for i in range(n):
            if t[i] not in hashmap2:
                hashmap2[t[i]] = s[i]
            elif hashmap2.get(t[i]) != s[i]:
                return False
        return True

思路2:元素第一次出现的索引

  1. 使用列表生成式,对s和t进行操作。
  2. 列表中的每个元素为:字符串的每个元素在字符串中第一次出现的索引值。
  3. 判等。

代码实现2:

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
    	return [s.index(i) for i in s] == [t.index(i) for i in t]

290. 单词规律

  • 给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。
    这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。

示例:

示例1:
输入: pattern = "abba", str = "dog cat cat dog"
输出: true

示例 2:
输入:pattern = "abba", str = "dog cat cat fish"
输出: false

示例 3:
输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false

示例 4:
输入: pattern = "abba", str = "dog dog dog dog"
输出: false

思路1:哈希表

先将str转为列表lst,判断列表长度与pattern字符串长度是否相等,不相等直接返回False。
建立 p a t t e r n − > l s t pattern->lst pattern>lst l s t − > p a t t e r n lst->pattern lst>pattern 之间的映射关系。
遍历pattern,哈希表中没有当前字符的映射,则添加映射进哈希表,如果映射已经存在,判断当前映射关系是否正确。
遍历str,重复上述操作。

代码实现1:

class Solution:
    def wordPattern(self, pattern: str, str: str) -> bool:
        hashmap1 = {}
        hashmap2 = {}

        lst = str.split(' ')
        if len(pattern) != len(lst):
            return False

        for i in range(len(pattern)):
            if pattern[i] not in hashmap1:
                hashmap1[pattern[i]] = lst[i]
            elif hashmap1.get(pattern[i]) != lst[i]:
                return False

        for i in range(len(pattern)):
            if lst[i] not in hashmap2:
                hashmap2[lst[i]] = pattern[i]
            elif hashmap2.get(lst[i]) != pattern[i]:
                return False
        
        return True

思路2:元素第一次出现的索引

  1. 使用列表生成式,对pattren和str进行操作,str需转为列表。
  2. 列表中的每个元素为:字符串的每个元素在字符串中第一次出现的索引值。
  3. 判等。

代码实现2:

class Solution:
    def wordPattern(self, pattern: str, str: str) -> bool:
        a = [pattern.index(i) for i in pattern]
        lst = str.split(' ')
        b = [lst.index(i) for i in lst]
        return a == b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值