344.反转字符串
题目:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
这道题虽然可以用reverse函数解决,但如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。
对于字符串,我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。
交换元素可以由swap实现,其中swap有两种实现方式:
1. 交换数值:
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
2. 位运算:
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
可以写出代码如下:
class Solution(object):
def reverseString(self, s):
left = 0
right = len(s) - 1
while left <= right:
a = s[left]
s[left] = s[right]
s[right] = a
left += 1
right -= 1
return s
交换还可以这么写:
s[left], s[right] = s[right], s[left]
或者使用栈:
stack = []
for char in s:
stack.append(char)
for i in range(len(s)):
s[i] = stack.pop()
使用reversed:
s[:] = reversed(s)
使用reverse:
s.reverse()
使用切片:
s[:] = s[::-1]
使用列表推导:
s[:] = [s[i] for i in range(len(s) - 1, -1, -1)]
时间复杂度: O(n)
空间复杂度: O(1)
541. 反转字符串II
题目:给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。如果剩余字符少于 k 个,则将剩余字符全部反转。如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
代码如下:
class Solution(object):
def reverseStr(self, s, k):
def reverse(s): # 要定义在类里面,函数不需要加self
left = 0
right = len(s) - 1
while left <= right:
s[left], s[right] = s[right], s[left]
# Python 中的字符串是不可变的,会报错,要转化成列表
left += 1
right -= 1
return s
s = list(s)
i = 0
while i < len(s):
s[i:i+k] = reverse(s[i:i+k])
i += 2*k
return ''.join(s) # 将列表转换回字符串
时间复杂度: O(n)
空间复杂度: O(1)
卡码网:54.替换数字
题目:给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。
步骤如下:
1. 首先扩充数组到每个数字字符替换成 "number" 之后的大小(不用申请新数组)。
2. 然后从后向前替换数字字符,也就是双指针法,过程如下:
i指向新长度的末尾,j指向旧长度的末尾。(从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动)
用python可以直接替换,代码如下:
class Solution:
def replace(self,s:str)->str:
s = list(s)
for i in range(len(s)):
if ord("0") <= ord(s[i]) <= ord("9"):
s[i] = "number"
return "".join(s)
solution = Solution()
s = input()
result = solution.replace(s)
print(result)
时间复杂度:O(n)
空间复杂度:O(1)
151.翻转字符串里的单词
题目:给定一个字符串,逐个翻转字符串中的每个单词。输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
如果要做到:不要使用辅助空间,空间复杂度要求为O(1)。还是有一定难度的。
思路如下:
1. 移除多余空格(双指针法,resize字符串大小)
2. 将整个字符串反转
3. 将每个单词反转
代码如下(删除空格部分一直有问题):
class Solution(object):
def reverseWords(self, s):
# def reverse(s, start, end):
# while start < end:
# s[start], s[end] = s[end], s[start]
# start, end = start + 1, end - 1
# # 将字符串转换为列表以便操作
# s = list(s)
# slow = 0
# # 重新排列单词,去除额外的空格
# for i in range(len(s)):
# if s[i] != ' ':
# if slow != 0:
# s[slow] = ' '
# slow += 1
# while i < len(s) and s[i] != ' ':
# s[slow] = s[i]
# slow += 1
# i += 1
# # 裁剪列表以移除末尾的额外空格
# s = s[:slow]
# # 反转整个字符串
# reverse(s, 0, len(s) - 1)
# # 反转每个单词
# start = 0
# for i in range(len(s) + 1):
# if i == len(s) or s[i] == " ":
# reverse(s, start, i - 1)
# start = i + 1
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) # 这里注意加空格
Python可以用strip函数:
class Solution:
def reverseWords(self, s: str) -> str:
# 删除前后空白
s = s.strip()
# 反转整个字符串
s = s[::-1]
# 将字符串拆分为单词,并反转每个单词
s = ' '.join(word[::-1] for word in s.split())
return s
或者split函数:
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)
时间复杂度: O(n)
空间复杂度: O(1) 或 O(n),取决于语言中字符串是否可变
卡码网:55.右旋转字符串
题目:字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
使用整体反转+局部反转就可以实现反转单词顺序的目的。
1. 我们需要将字符串右移n位,字符串相当于分成了两个部分,如果n为2,符串相当于分成了两个部分
2. 右移n位, 就是将第二段放在前面,第一段放在后面,先不考虑里面字符的顺序,是不是整体倒叙不就行了
3. 此时第一段和第二段的顺序是我们想要的,但里面的字符位置被我们倒叙,那么此时我们在把 第一段和第二段里面的字符再倒叙一把,这样字符顺序不就正确了
其实,思路就是 通过 整体倒叙,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把,负负得正,这样就不影响子串里面字符的顺序了。
代码如下:
k = int(input()) #要加int,不然读取的是字符串
s = input()
s = list(s)
s.reverse()
s[:k] = reversed(s[:k]) #这里不用k-1
s[k:] = reversed(s[k:])
s = ''.join(s)
print(s)