代码随想录算法训练营第八天|哈希表理论基础、LeetCode344 反转字符串、LeetCode541 反转字符串Ⅱ、卡码网54 替换数字、LeetCode151 翻转字符串里的单词、卡码网55 右旋转字符串
LeetCode344 反转字符串
题目链接:https://leetcode.cn/problems/reverse-string/description/
- 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
代码描述
方法一:双指针法
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
双指针
时间复杂度:O(n)
空间复杂度:O(1)
"""
low, fast = 0, len(s) - 1
while low < fast:
# s[left], s[right] = s[right], s[left] 其实可以直接使用这个语句
a = s[fast]
s[fast] = s[low]
s[low] = a
low += 1
fast -= 1
方法二:使用range()
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
使用range()
时间复杂度:O(n)
空间复杂度:O(1)
"""
n = len(s)
for i in range(n // 2):
s[i], s[n - i - 1] = s[n - i - 1], s[i]
方法三:使用reverse()方法
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
使用reverse()方法
时间复杂度:O(n)
空间复杂度:O(1)
"""
# 原地反转,无返回值
s.reverse()
LeetCode541 反转字符串Ⅱ
题目链接:https://leetcode.cn/problems/reverse-string-ii/description/
- 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
代码描述
错误代码:
class Solution:
def reverseStr(self, s: str, k: int) -> str:
l = len(s)
for i in range(0, l, 2 * k):
if i + k <= l:
s[i:i + k] = s[i:i + k][::-1]
continue
s[i:l] = s[i:l][::-1]
return s
错误原因:字符串本身是不可变的,不能直接对字符串进行切片修改,可以将字符串改为转成列表进行修改,返回结果时再转回①;也可以对字符串切片并拼接,然后再赋值②
修改方法①:
class Solution:
def reverseStr(self, s: str, k: int) -> str:
l = len(s)
res = list(s)
for i in range(0, l, 2 * k):
if i + k <= l:
res[i:i + k] = res[i:i + k][::-1]
continue
res[i:l] = res[i:l][::-1]
return ''.join(res)
注意:
- 不能直接返回res。假设s = “abcdefg”, k = 2, 如果直接输出或转换成字符串输出,则有
返回形式:return res
期望输出:"bacdfeg"
实际输出:["b","a","c","d","f","e","g"]
返回形式:return str(res)
期望输出:"bacdfeg"
实际输出:"["b","a","c","d","f","e","g"]"
- ‘’.join(res)是一个字符串方法,它将可迭代的元素(在本例中为 list res)连接成单个字符串。空字符串’'用作分隔符,这意味着元素将被连接在一起,中间不包含任何字符。举例来说:
res = ['abc', 'def', 'ghi']
result1 = ''.join(res)
result2 = '_'.join(res)
print(result1)
print(result2)
输出:
abcdefghi
abc_def_ghi
- s[p: p2][::-1]是一个切片操作,表示让字符串s从索引p到索引p2-1进行反转操作。[::-1]就是取步长为-1的切片,也就是反转。举例来说:
s = "abcdefgh"
result = s[2:6][::-1]
print(result)
输出结果就是:fedc
修改方法②:
class Solution:
def reverseStr(self, s: str, k: int) -> str:
l = len(s)
res = []
for i in range(0, l, 2 * k):
if i + k <= l:
res.extend(s[i:i + k][::-1])
res.extend(s[i + k:i + 2 * k])
continue
res.extend(s[i:l][::-1])
return ''.join(res)
还有一种切片解题方式:
class Solution:
def reverseStr(self, s: str, k: int) -> str:
# Two pointers. Another is inside the loop.
p = 0
while p < len(s):
p2 = p + k
# Written in this could be more pythonic.
s = s[:p] + s[p: p2][::-1] + s[p2:]
p = p + 2 * k
return s
卡码网54 替换数字
题目链接:https://kamacoder.com/problempage.php?pid=1064
- 给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anumberbnumbercnumber”。
代码描述
class Solution:
def transfernum(self, s:str) -> str:
''' 时间复杂度:O(n)
空间复杂度:O(n)
'''
len_1 = len(s)
count = 0 # 数字的个数
for char in s:
if "0" <= char <= "9": #根据ASCII来的
# if char.isdigit(): #s.isdigit()如果给定字符串中的所有字符都是数字,则返回 True,否则返回 False。
count += 1
len_2 = len(s) + 5 * count
res = "" * len_2
cur = list(res)
for char in s:
if "0" <= char <= "9":
cur.extend('number')
continue
else:
cur.extend(char)
return ''.join(cur)
sol = Solution()
s = input()
result = sol.transfernum(s)
print(result)
想复杂了其实,可以简单一点写:
class Solution:
def transfernum(self, s:str) -> str:
''' 时间复杂度:O(n)
空间复杂度:O(n)
'''
len_1 = len(s)
res = list(s)
for i in range(len_1):
if "0" <= res[i] <= "9": #根据ASCII来的
# if res[i].isdigit(): #s.isdigit()如果给定字符串中的所有字符都是数字,则返回 True,否则返回 False。
res[i] = 'number'
return ''.join(res)
sol = Solution()
s = input()
result = sol.transfernum(s)
print(result)
- 保证extend或者append的时候是列表,而不是字符串,python中的字符串是无法更改的
- 记得最后return的是’'.joint(s)
LeetCode151 翻转字符串里的单词
题目链接:https://leetcode.cn/problems/reverse-words-in-a-string/description/
- 给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
代码描述
方法一:先删除空白,然后整个反转,最后单词反转。注意字符串不可变。
class Solution:
def reverseWords(self, s: str) -> str:
s = s.strip() # 删除前后空白
s = s[::-1] # 反转整个字符串
s = ' '.join(word[::-1] for word in s.split()) # 将字符串拆分成单词【列表】,每个单词再反转,之后用.join()转换成字符串
return s
知识点:
- strip()函数用于移除字符串头与尾的指定字符或字符序列(默认移除空格或换行符)
str.strip() # 默认移除字符串str前后的所有空格
str.strip("*") # 移除字符串str前后的所有*符号
- split()函数将字符串分割成列表。默认以空格分隔。
s = "hello world"
s.split()
s = "a,b,c,d"
s.split(',')
输出:
['hello', 'world']
['a', 'b', 'c', 'd']
方法二:双指针法:
class Solution:
def reverseWords(self, s: str) -> str:
words = s.split() # 拆分成单词(转换成列表)
# 反转单词
left, right = 0, len(words) - 1
while left < right:
words[left], words[right] = words[right], words[left]
left += 1
right -= 1
# 列表转换为字符串
return " ".join(words)