字符串
1、反转字符串
编写一个函数,其作用是将输入的字符串反转过来,输入字符串以字符数组s的形式给出
不要给另外的数组分配额外的空间,你必须原地修改数组、使用O(1)的额外空间解决这一问题
输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]
class Solution:
def reverseString(self, s):
left, right = 0, len(s)-1
while left < right:
s[left], s[right] = s[right], s[left]
left += 1
right -= 1
2、反转字符串II
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转
- 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
class Solution:
def reverseStr(self, s, k):
s = list(s)
lens = len(s)
left, right = 0, 2k
while right <lens:
s[left: right-k] = self.reverse(s[left, right-k])
if lens - left < k:
s[left:] = self.reverse(s[left:])
else:
s[left, left+k] = self.reverse(s[left: left+k])
return "".join(s)
def reverse(self, s):
i, j = 0, len(s)
while i < j:
s[i], s[j] = s[j], s[i]
i += 1
j -= 1
return s
3、替换空格
剑指 Offer 05. 替换空格 - 力扣(LeetCode)
请实现一个函数,把字符串 s
中的每个空格替换成"%20"。
输入:s = "We are happy."
输出:"We%20are%20happy."
class Solution:
def replaceSpace(self, s):
s = list(s)
for i in range(len(s)):
if s[i] == " ":
s[i] = "%20"
return "".join(s)
4、颠倒字符串中的单词
给你一个字符串 s
,颠倒字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
**注意:**输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
输入:s = "the sky is blue"
输出:"blue is sky the"
class Solution:
def reversewords(self, s):
#去除前导空格, 尾随空格
s= list(s)
left, right = 0, len(s) - 1'
while left <right and s[left] == ' ':
left += 1
while left < right and s[right] == ' ':
right -= 1
tmp []
#去除单词间多余空格
while left <= right:
if s[left] != ' ':
tmp.append(s[left])
elif tmp[-1] != ' ':
tmp.append(s[left])
left += 1
n = len(tmp)
left, right = 0, 0
while right < n:
while right < n and tmp[right] != ' ':
right += 1
tmp = self.reverse(tmp, left, right-1)
left = right + 1
right = left
return "".join(tmp)
def reverse(self, s, left, right):
i, j = left, right
while i < j:
tmp[i], tmp[j] = tmp[j], tmp[i]
i += 1
j -= 1
return s
5、左旋转字符串
剑指 Offer 58 - II. 左旋转字符串 - 力扣(LeetCode)
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能,比如,输入字符串“abcdefg"和数字2, 该函数将返回左旋转两位得到的结果’‘cdefgab’’
输入: s = "abcdefg", k = 2
输出: "cdefgab"
class Solution:
def reverseLeftwords(self, s, n):
s = list(s)
s[:n] = self.reverse(s[:n])
s[n:] = self.reverse(s[n:])
s[:] = self.reverse(s[:])
return "".join(s)
def reverse(self, s):
i, j = 0, len(s) - 1
while i < j:
s[i], s[j] = s[j], s[i]
i += 1
j -= 1
return s
6、实现strStr()
28. 实现 strStr() - 力扣(LeetCode)
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出needle
字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1
。
说明:
当 needle
是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
KMP算法
kmp算法主要应用在字符串匹配上,主要思想是**当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了****
next数组:前缀表, 用来回退的,它记录了模式串与主串(文本串)不匹配时,模式串应该从哪里开始重新匹配
前缀表的任务是当前位置匹配失败,找到之前已经匹配的位置,再重新匹配,也意味着在某个字符失配时,前缀表会告诉你下一步匹配时,模式串应该跳到哪个位置
前缀:不包含最后一个字符的所有以第一个字符开头的连续子串
后缀:不包含第一个字符的所有以最后一个字符结尾的连续子串
**举例:**aabaaf
a
:前缀为空,后缀为空,最长相同前后缀为0
aa
: 前缀为a
, 后缀为a
, 最长相同前后缀为1
aab
:前缀为a, aa
, 后缀为ab, b
, 最长相同前后缀为0
aaba
:前缀为a, aa, aab
, 后缀为aba, ba, a
,最长相同前后缀为1
aabaa
:前缀为a, aa, aab, aaba
, 后缀为abaa, baa, aa, a
, 最长相同前后缀为2
aabaaf
:前缀为a, aa, aab, aaba, aabaa
, 后缀为abaaf, baaf, aaf, af, f
, 最长相同前后缀为0
因此,前缀表为[0, 1, 0, 1, 2, 0]
next数组为将前缀表-1操作
构造next数组
1、初始化, 定义两个指针i和j, j指向前缀末尾位置,i 指向后缀末尾位置
def getNext(next, s):
j = -1
next[0] = j
for i in range(1, len(s)):
while j >= 0 and s[i] != s[j+1]:
j = next[j]
if s[i] == s[j+1]:
j += 1
next[i] = j
使用next数组,用模式串匹配文本串的整体代码如下:
int j = -1
for i in range(len(s)):
while j >= 0 and s[i] != t[j+1]:
j = next[j]
if s[i] == t[j + 1]:
j += 1
if j == len(t) - 1:
return i - t.size() + 1
总体代码
class Solution:
def strStr(self, haystack, needle):
next = [0] * len(needle)
self.getNext(next, needle)
j = -1
for i in range(len(haystack)):
while j >= 0 and haystack[i] != needle[j+1]:
j = next[j]
if haystack[i] == needle[j+1]:
j += 1
if j == len(needle) - 1:
return i - len(needle) + 1
def getNext(self, next, needle):
j = -1
next[0] = j
for i in range(1, len(needle)):
while j >= 0 and needle[i] != needle[j+1]:
j = next[j]
if needle[i] == needle[j+1]:
j += 1
next[i] = j
7、重复的子字符串
给定一个非空的字符串s
,检查是否可以通过由它的一个子串重复 多次构成
输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。
数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环
class Solution:
def repeatedSubstringPattern(self, s):
next = [0] * len(s)
self.getNext(next, s)
lens = len(s)
if next[lens-1] != -1 and lens % (lens - (next[lens-1] + 1)) == 0:
return True
return False
def getNext(self, next, s):
j = -1
next[0] = j
for i in range(1, len(s)):
while j >= 0 and s[i] != s[j+1]:
j = next[j]
if s[i] == s[j+1]:
j += 1
next[i] = j