58. 最后一个单词的长度
方法一:反向遍历
class Solution:
def lengthOfLastWord(self, s: str) -> int:
s = s.strip() # 处理后面的空格
n = len(s)
for i in range(n-1, -1, -1):
if s[i] == ' ':
return n - i - 1
return n # 只有一个单词
# return len(s.split()[-1])
1、1957. 删除字符使字符串变好
知识点: 字符串(索引、切片、长度),len,!=,+=,in (not in) ,or 和 for。
教程:Python 1-09 字符串
class Solution:
def makeFancyString(self, s: str) -> str:
# n = len(s)
# if n < 3: return s
res = s[:2]
for c in s[2:]:
if c != res[-1] or c != res[-2]:
res += c
return res
2、1221. 分割平衡字符串
class Solution:
def balancedStringSplit(self, s: str) -> int:
res = d = 0
for ch in s:
d += (1 if ch == "R" else -1)
if d == 0: res += 1
return res
3、796. 旋转字符串
知识点: find,True,False,all,%
方法一:穷举法
class Solution:
def rotateString(self, s: str, goal: str) -> bool:
m, n = len(s), len(goal)
if m != n: return False
if m == 0: return True
# if s == goal: return True
for i in range(n):
# if all(s[(i+j) % n] == goal[j] for j in range(n)):
# return True
s = s[1:] + s[0]
if s == goal: return True
return False
方法二:判断子串
先判断长度是否相同,不相同返回 False,其次拼接两个 s,则如果 goal 是由 s 旋转而成,则拼接后的 s 一定包含 goal。
class Solution:
def rotateString(self, s: str, goal: str) -> bool:
# if len(s) != len(goal): return False
# return goal in s * 2
# return len(s) == len(goal) and (s * 2).find(goal) != -1
return len(s) == len(goal) and goal in s * 2
4、1768. 交替合并字符串
方法一:
class Solution:
def mergeAlternately(self, word1: str, word2: str) -> str:
x, res = min(len(word1), len(word2)), ''
for i in range(x):
res += word1[i] + word2[i]
res += word1[x:] + word2[x:] # 处理剩余的部分
return res
方法二:队列,zip_longest
class Solution:
def mergeAlternately(self, word1: str, word2: str) -> str:
# a, b = deque(word1), deque(word2)
# res = ""
# while a and b:
# res += a.popleft()
# res += b.popleft()
# res += "".join(a) + "".join(b)
# return res
# from itertools import zip_longest
return "".join(sum(zip_longest(word1, word2, fillvalue=""), ()))
5、面试题 01.06. 字符串压缩
class Solution:
def compressString(self, S: str) -> str:
# n, res, i = len(S), '', 0
# while i < n:
# j = i
# while j < n and S[j] == S[i]:
# j += 1
# res += S[i] + str(j - i)
# i = j
if not S: return S
tmp, cnt, res = S[0], 0, ''
for c in S:
if c == tmp:
cnt += 1
else:
res += tmp + str(cnt)
tmp, cnt = c, 1
res += tmp + str(cnt)
return res if len(res) < len(S) else S
6、415. 字符串相加
知识点: divmod,//,%,str,int,if … else …
方法一:模拟
设定 i,j 两指针分别指向 num1,num2 尾部,模拟人工加法;
计算进位: 计算 carry = tmp // 10,代表当前位相加是否产生进位;
添加当前位: 计算 tmp = n1 + n2 + carry,并将当前位 tmp % 10 添加至 res 头部;
索引溢出处理: 当指针 i 或 j 走过数字首部后,给 n1,n2 赋值为 0,相当于给 num1,num2 中长度较短的数字前面填 0,以便后续计算。
当遍历完 num1,num2 后跳出循环,并根据 carry 值决定是否在头部添加进位 1,最终返回 res 即可。
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
res = ""
i, j, carry = len(num1) - 1, len(num2) - 1, 0
while i >= 0 or j >= 0:
n1 = int(num1[i]) if i >= 0 else 0
n2 = int(num2[j]) if j >= 0 else 0
tmp = n1 + n2 + carry
carry, rem = divmod(tmp, 10) # carry = tmp // 10 ;rem = tmp % 10
res = str(rem) + res
i, j = i - 1, j - 1 # i -= 1; j -= 1
return "1" + res if carry else res
# return str(int(num1) + int(num2))
7、387. 字符串中的第一个唯一字符
方法一:dict
class Solution:
def firstUniqChar(self, s: str) -> int:
# d = defaultdict(int)
# for c in s:
# d[c] += 1
d = collections.Counter(s)
for i, c in enumerate(s):
if d[c] == 1:
return i
return -1
方法二:find rfind
class Solution:
def firstUniqChar(self, s: str) -> int:
for i, c in enumerate(s):
if s.find(c) == s.rfind(c):
return i
return -1
方法三:set
class Solution:
def firstUniqChar(self, s: str) -> int:
seen = set()
for i, c in enumerate(s):
if s.rfind(c) == i and c not in seen:
return i
else:
seen.add(c)
return -1
8、344. 反转字符串
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
# i, j = 0, len(s)-1
# while i < j:
# s[i], s[j] = s[j], s[i]
# i += 1
# j -= 1
for i in range(len(s)//2):
s[i], s[-i-1] = s[-i-1], s[i]
# s[:] = s[::-1]
9、1417. 重新格式化字符串
class Solution:
def reformat(self, s: str) -> str:
nums, string, res = [], [], ''
for c in s:
if c.isdigit(): nums.append(c)
else: string.append(c)
m, n = len(string), len(nums)
if abs(m - n) > 1:
return ""
if m > n:
for i in range(n):
res += string[i] + nums[i]
res += string[-1]
else:
for i in range(m):
res += nums[i] + string[i]
if m < n:
res += nums[-1]
return res
10、2000. 反转单词前缀
class Solution:
def reversePrefix(self, word: str, ch: str) -> str:
idx = word.find(ch)
return word[:idx+1][::-1] + word[idx+1:] if idx != -1 else word
1796. 字符串中第二大的数字
class Solution:
def secondHighest(self, s: str) -> int:
# 方法一:
# res = first = second = -1
# for c in s:
# if c.isdigit():
# d = int(c)
# if d > first:
# first, second = d, first
# else:
# if first > d > second:
# second = d
# return second
# 方法二:list sort
# digit = []
# for c in s:
# if c.isdigit() and int(c) not in digit:
# digit.append(int(c))
# digit.sort()
# return digit[-2] if len(digit) > 1 else -1
# 方法三:filter list sort map 高阶函数
digit = sorted(map(int, set(filter(str.isdigit, s)))) # 过滤英文字母
return digit[-2] if len(digit) > 1 else -1
1790. 仅执行一次字符串交换能否使两个字符串相等
class Solution:
def areAlmostEqual(self, s1: str, s2: str) -> bool:
first = second = False
for i, c in enumerate(s1):
if s2[i] != c:
if not first: # 第一次不同,记录下来。
first = True
x = s2[i]
y = c
elif not second: # 第二次不同
if c != x or s2[i] != y:return False
second = True
else:
return False
return not first or (first and second)
class Solution:
def areAlmostEqual(self, s1: str, s2: str) -> bool:
if sorted(s1) != sorted(s2): return False
first = second = True
for i, c in enumerate(s1):
if s2[i] != c:
if first:
first = False
elif second:
second = False
else:
return False
return True
1446. 连续字符
class Solution:
def maxPower(self, s: str) -> int:
res = tmp = 1
x = s[0]
for i in range(1, len(s)):
if s[i] == x:
tmp += 1
else:
res = max(res, tmp)
x = s[i]
tmp = 1
return max(res, tmp)