题目描述
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每计数至 2k
个字符,就反转这 2k
字符中的前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转。 - 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
示例 1:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
示例 2:
输入: s = "abcd", k = 2
输出: "bacd"
提示:
1 <= s.length <= 104
s
仅由小写英文组成1 <= k <= 104
分析解答
思路就是一个反转字符串的问题。这道题重点在于反转的规则。
规则是一个 k 和 2k 的范围限制。用 "abcdefg" 来举个例子。"abcd" 为一组,满足 2k,反转"ab","efg" 为一组,满足 k < length < 2k,反转 "ef"。但是我们改一下,改为一种特殊情况, "efg' -> "e",则将剩余的 "e" 全部反转。
规则大致说清楚了,然后用代码解决就不难了。但但是,我用的是 js,直接反转 reverse 方法,不是对原字符串进行操作,而是 copy 一个操作完进行返回,赋值给其他变量。然后因为还有一些不变的字符,需要再对他们进行拼接,就有一些麻烦。
思路拓展
所以我们可以上来就将字符串转为数组,最后再将数组合并成为字符串。
最后层循环 i 可以用来限定范围的起始点,然后范围的总长度为 2k,因为条件就是 i += 2 * k。
进入这个范围区间,就简单了。利用双指针进行操作交换。
这里再注意的=一下右指针,因为如果剩余字符少于 k
个,则将剩余字符全部反转。而又因为我们在每个范围内需要反转的字符始终小于或等于 k 个。所以不需要考虑 i = 2 * k 是否已超出了数组的最大长度。由以上可以得出右指针的判断条件:r = (i + k) > resArr.length ? resArr.length : i + k
。
当然,由于这里的左右指针还是左闭右开的,在遍历交换的时候还需要注意交换的是 r - 1。
以下是代码:
js
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
var reverseStr = function (s, k) {
let resArr = s.split('')
for (let i = 0; i < resArr.length; i += 2 * k) {
let l = i
let r = (i + k) > resArr.length ? resArr.length : i + k
while (l < r - 1) {
[resArr[l], resArr[r - 1]] = [resArr[r - 1], resArr[l]]
l++
r--
}
}
return resArr.join('')
};
let s = "abcd"
let res = reverseStr(s, 2)
console.log(res)