1. 字符串循环移位包含
s1 = AABCD, s2 = CDAA
Return : true
给定两个字符串 s1 和 s2,要求判定 s2 是否能够被 s1 做循环移位得到的字符串包含。
s1 进行循环移位的结果是 s1s1 的子字符串,因此只要判断 s2 是否是 s1s1 的子字符串即可。
def isContainsByConcal(a, b):
if not a or not b: return False
new_a = a + a
return b in new_a
2. 字符串循环移位
s = "abcd123" k = 3
Return "123abcd"
将字符串向右循环移动 k 位。
将 abcd123 中的 abcd 和 123 单独翻转,得到 dcba321,然后对整个字符串进行翻转,得到 123abcd。
def leftloop(lst, k):
return lst[k:] + lst[:k]
def leftloop(lst, k):
new = lst[:k][::-1] + lst[k:][::-1]
return new[::-1]
3. 字符串中单词的翻转
s = "I am a student"
Return "student a am I"
将每个单词翻转,然后将整个字符串翻转。
def revereseWords(s):
ls = s.split(" ")
new_str = ls.reverse()
return " ".join(new_str)
4. 两个字符串包含的字符是否完全相同
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.
可以用 HashMap 来映射字符与出现次数,然后比较两个字符串出现的字符数量是否相同。
由于本题的字符串只包含 26 个小写字符,因此可以使用长度为 26 的整型数组对字符串出现的字符进行统计,不再使用 HashMap。
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
cnts = [0] * 26
for c in s:
cnts[ord(c) - ord('a')] += 1
for c in t:
cnts[ord(c) - ord('a')] -= 1
for cnt in cnts:
if cnt != 0:
return False
return True
5. 计算一组字符集合可以组成的回文字符串的最大长度
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 "Aa"
不能当做一个回文字符串。
Input : "abccccdd"
Output : 7
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
使用长度为 256 的整型数组来统计每个字符出现的个数,每个字符有偶数个可以用来构成回文字符串。
因为回文字符串最中间的那个字符可以单独出现,所以如果有单独的字符就把它放到最中间。
class Solution:
def longestPalindrome(self, s: str) -> int:
cnts = [0] * 256
for c in s:
cnts[ord(c)] += 1
palindrome = 0
for cnt in cnts:
palindrome += cnt // 2 * 2
if palindrome < len(s):
palindrome += 1 # 这个条件下 s 中一定有单个未使用的字符存在,可以把这个字符放到回文的最中间
return palindrome
6. 字符串同构
给定两个字符串 s 和 t,判断它们是否是同构的。
如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。 假设 s 和 t 具有相同的长度。
Given "egg", "add", return true.
Given "foo", "bar", return false.
Given "paper", "title", return true.
记录一个字符上次出现的位置,如果两个字符串中的字符上次出现的位置一样,那么就属于同构。
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
preIndexOfS = [0] * 256
preIndexOfT = [0] * 256
for i in range(len(s)):
if preIndexOfS[ord(s[i])] != preIndexOfT[ord(t[i])]:
return False
preIndexOfS[ord(s[i])] = i + 1 # 记录位置信息
preIndexOfT[ord(t[i])] = i + 1
return True
将 s 与 t 中的元素利用哈希表 (字典) 一一对应,后面重复的字符与哈希表中字符对应规则一致则说明同构。
class Solution(object):
def isIsomorphic(self, s, t):
if not s:
return True
dic = {}
for i in range(len(s)):
if s[i] not in dic:
if t[i] in dic.values():
return False
else:
dic[s[i]] = t[i]
else:
if dic[s[i]] != t[i]:
return False
return True
7. 回文子字符串个数
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。
输入: "aaa"
输出: 6
说明: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa".
在长度为 N 的字符串中,可能的回文串中心位置有 2N-1 个:一个字母,或两个字母中间。
从每一个回文串中心开始统计回文串数量。回文区间 [a, b] 表示 S[a], S[a+1], …, S[b] 是回文串,根据回文串定义可知 [a+1, b-1] 也是回文区间。
class Solution(object):
def countSubstrings(self, S):
N = len(S)
ans = 0
for center in range(2*N - 1):
left = center // 2 # center 为奇数时,center 为两字母之间,;left、right 分别为两字母位置的下标
right = left + center % 2 # 偶数时,left、right 为中心位置的下标
while left >= 0 and right < N and S[left] == S[right]:
ans += 1
left -= 1
right += 1
return ans
从字符串的某一位开始,尝试着去扩展子字符串。
class Solution:
def countSubstrings(self, s: str) -> int:
self.ans = 0
def extendSubStrings(s, start, end):
while start >= 0 and end < len(s) and s[start] == s[end]:
start -= 1
end += 1
self.ans += 1
for i in range(len(s)):
extendSubStrings(s, i, i)
extendSubStrings(s, i, i + 1)
return self.ans
8. 判断一个整数是否是回文数
要求不能使用额外空间,也就不能将整数转换为字符串进行判断。
将整数翻转:
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0:
return False
cur = 0
num = x
while num != 0:
cur = cur * 10 + num % 10
num = num // 10
return x == cur
将整数分成左右两部分,右边那部分需要转置,然后判断这两部分是否相等。
class Solution:
def isPalindrome(self, x: int) -> bool:
if x == 0: return True
if x < 0 or x % 10 == 0: return False
right = 0
while x > right:
right = right * 10 + x % 10
x = x // 10
return x == right or x == right // 10
9. 统计二进制字符串中连续 1 和连续 0 数量相同的子字符串个数
输入: "00110011"
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
- 按字符分组:
- 将字符串 s 转换为 groups 数组表示字符串中相同字符连续块的长度。例如,如果 s=“11000111000000”,则 groups=[2,3,3,6]
- 计算 groups[i] 和 groups[i+1] 之间的有效二进制字符串数。如果我们有 groups[i] = 2, groups[i+1] = 3,那么它表示 “00111” 或 “11000”。显然,我们可以在此字符串中生成 min(groups[i], groups[i+1]) 有效的二进制字符串。
class Solution(object):
def countBinarySubstrings(self, s):
groups = [1]
for i in range(1, len(s)):
if s[i-1] != s[i]:
groups.append(1)
else:
groups[-1] += 1
ans = 0
for i in range(1, len(groups)):
ans += min(groups[i-1], groups[i])
return ans
- 线性扫描:
修改我们的方法 1 来实时计算答案。我们将**只记住 prev = groups[-2] 和 cur=groups[-1] **来代替 groups。然后,答案是我们看到的每个不同的 (prev, cur) 的 min(prev, cur) 之和。
class Solution(object):
def countBinarySubstrings(self, s):
ans, prev, cur = 0, 0, 1
for i in range(1, len(s)):
if s[i-1] != s[i]:
ans += min(prev, cur)
prev, cur = cur, 1
else:
cur += 1 # 记录当前重复的字符
return ans + min(prev, cur)