Table of Contents
344. 反转字符串
简单
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组
s的形式给出。不要给另外的数组分配额外的空间,你必须**原地修改输入数组**、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = ["h","e","l","l","o"]输出:["o","l","l","e","h"]示例 2:
输入:s = ["H","a","n","n","a","h"]输出:["h","a","n","n","a","H"]提示:
1 <= s.length <= 105s[i]都是 ASCII 码表中的可打印字符
用 left 和 right 双指针, for left < right {} 循环直接反转字符串即可。不要习惯性地 for i:=0; i<len; i++ {}。
func reverseString(s []byte) { left := 0 right := len(s) - 1 for left < right { s[left], s[right] = s[right], s[left] left++ right-- }}541.反转字符串 II
简单
给定一个字符串
s和一个整数k,从字符串开头算起,每计数至2k个字符,就反转这2k字符中的前k个字符。
如果剩余字符少于
k个,则将剩余字符全部反转。如果剩余字符小于
2k但大于或等于k个,则反转前k个字符,其余字符保持原样。示例 1:
输入:s = "abcdefg", k = 2输出:"bacdfeg"示例 2:
输入:s = "abcd", k = 2输出:"bacd"提示:
1 <= s.length <= 104s仅由小写英文组成1 <= k <= 104
思路
- 每隔 2k 个字符的前 k 个字符进行反转
- 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
PS:反转函数和344.反转字符串一样,直接使用库函数也可以。许多库函数的区间都是左闭右开的。
这道题用Go写可以对 s 进行切片,直接对底层数组进行反转操作。
func reverseStr(s string, k int) string { ss := []byte(s) len := len(ss) for i := 0; i < len; i += 2*k { if i + k <= len { // 1,2,3 k==2 // 反转 i ~ i+k (前k个),凑足k个反转 reverse(ss[i:i+k]) // 左闭右开 } else { // 剩余的不足k个,剩下的都反转 reverse(ss[i:len]) } } return string(ss)}
func reverse(s []byte) []byte{ left := 0 right := len(s)-1 for left < right { s[left], s[right] = s[right], s[left] left++ right-- } return s}151. 反转字符串中的单词
中等
给你一个字符串
s,请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。
s中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
**注意:**输入字符串
s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。示例 1:
输入:s = "the sky is blue"输出:"blue is sky the"示例 2:
输入:s = " hello world "输出:"world hello"解释:反转后的字符串中不能存在前导空格和尾随空格。示例 3:
输入:s = "a good example"输出:"example good a"解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。提示:
1 <= s.length <= 104
s包含英文大小写字母、数字和空格' '
s中 至少存在一个 单词**进阶:**如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用
O(1)额外空间复杂度的 原地 解法。
本题增加难度,在原地进行操作。在 go 语言中将字符串转换为 []byte 来操作。
1. 双指针法(快慢指针)来去除多余的空格。
当快指针 i 读到字母(非空格字符时),开始处理需要写入的内容。
- 在每个单词前加一个空格(首个单词除外)
// 单词间加上空格if slow != 0 { ss[slow] = ' ' slow++}- 把需要复制的字符,复制到慢指针,随后快慢指针向后移动(即原地覆盖字符串),截断字符串到有效部分。
2. 翻转字符串
先翻转整个字符串,再翻转每个单词,就实现了题目的要求。
翻转单词的思路就是记录 单词的开头位置,同时找到下一个空格或字符串末尾+1的索引 i,reverse(s[start, i]),实现对底层数组的修改。
for 循环的判断条件是 i <= len(s),因为到 i<len 是遍历到字符串末尾,切片操作是左闭右开,想要包含最后一个字符,就要把 i 向后多移一位。
接着 start = i + 1 (因为第 i 位是空格,下一位才是新的字母)
func reverseWords(s string) string { // 1. 双指针去除多余空格 ss := []byte(s) slow := 0 // 如果 slow == 0,开始复制字符串直到 i 遇到空格,下一次循环 // 这时 slow != 0,先加个空格,再继续复制字符串 // 这样就实现了去除多余空格 for i := 0; i < len(ss); i++ { if ss[i] != ' ' { // 单词间加上空格 if slow != 0 { ss[slow] = ' ' slow++ } // 复制逻辑 for i < len(ss) && ss[i] != ' ' { ss[slow] = ss[i] slow++ i++ } } } // 截断字符串到实际位置 ss = ss[0:slow]
// 2. 反转整个字符串 reverse(ss) // // 3. 反转每个单词 start := 0 for i := 0; i <= len(ss); i++ { if i == len(ss) || ss[i] == ' ' { reverse(ss[start:i]) // start 是单词的开头,而此时i指向空格或字符串末尾,i+1 才是下一个单词的开头 start = i + 1 } } return string(ss)}
func reverse(s []byte){ left := 0 right := len(s) - 1 for left < right { s[left], s[right] = s[right], s[left] left++ right-- }}