题目链接: leetcode344-反转字符串,leetcode541-反转字符串II,leetcode-151-反转字符串中的单词
反转字符串
时间复杂度: O(n)
空间复杂度: O(1)
Go
func reverseString(s []byte) {
left, right := 0, len(s)-1
for left < right {
s[left], s[right] = s[right], s[left]
left++
right--
}
}
反转字符串II
时间复杂度: O(n)
空间复杂度: O(1)
Go
func reverseStr(s string, k int) string {
sBytes := []byte(s)
sLen := len(s)
// 步数为2k
for i := 0; i < sLen; i += 2 * k {
if i+k <= sLen {
// 剩余的长度大于k,反转前k个
revS(sBytes, i, i+k-1)
} else {
// 剩余的字符小于k, 全部反转
revS(sBytes, i, sLen-1)
}
}
return string(sBytes)
}
func revS(s []byte, left, right int) {
for left < right {
s[left], s[right] = s[right], s[left]
left++
right--
}
}
反转字符串中的单词
思路:
- 去除首尾空格和中间连续的空格(连续的空格只保留一个)
- 反转整个字符串
- 反转字符串中的单词
时间复杂度: O(n)
空间复杂度: O(1) (Go切片的底层是一个数组,多个切片引用的可能是同一个数组)
Go
func reverseWords(s string) string {
sBytes := []byte(s)
// 去除首尾空格
sBytes = trimSpace(sBytes)
// 反转整个字符串
sLen := len(sBytes)
rev(sBytes, 0, sLen-1)
// 反转字符串中的单词
startIdx := 0
for i := 0; i <= sLen; i++ {
if i == sLen || sBytes[i] == ' ' {
rev(sBytes, startIdx, i-1)
startIdx = i + 1
}
}
return string(sBytes)
}
// 去除首位空格
func trimSpace(s []byte) []byte {
// slow指向的是有效数字
// 数组是不能删除元素的,只能重新排列有效元素
slow, fast := 0, 0
sLen := len(s)
for fast < sLen {
// 如果不为空格一定是有效数据
if s[fast] != ' ' {
s[slow] = s[fast]
slow++
fast++
} else {
// 如果是空格需要进行判断,只有中间的不连续的空格是有效的空格
// 先去除连续的空格
for fast < sLen && s[fast] == ' ' {
fast++
}
// 如果不是在头部或者尾部,说明是有效的空格
if slow > 0 && fast < sLen {
s[slow] = ' '
slow++
}
}
}
return s[0:slow]
}
func rev(s []byte, left, right int) {
for left < right {
s[left], s[right] = s[right], s[left]
left++
right--
}
}