前言
代码随想录是一本个常受欢迎的算法博客,其中包含了大量经典的算法题目和解法。而且非常适合小白入门学习算法,它的题目安排顺序难度是由浅入深的,博主卡尔的讲解也很清晰易懂。这里是链接--代码随想录
讲回我们的题目,右旋字符串是一个常见的字符串操作问题,可以通过多种方法解决。且听我娓娓道来。
问题描述
给定一个字符串 s 和一个整数 k,将字符串 s 右旋 k 个位置。右旋的意思是将字符串的最后 k 个字符移到字符串的前面。
示例
- 输入:
s = "abcdefg",k = 2 - 输出:
"fgabcde"
解法一:三次反转法
- 反转整个字符串。
- 反转前
k个字符。 - 反转剩下的字符。
这种方法的时间复杂度是 O(n),空间复杂度是 O(1)。
代码实现
function rightRotateString(s, k) {
if (!s || s.length === 0 || k <= 0) {
return s;
}
const n = s.length;
k = k % n; // 处理 k 大于字符串长度的情况
// 将字符串转换为数组,因为字符串是不可变的
let arr = s.split('');
// 反转整个字符串
reverse(arr, 0, n - 1);
// 反转前 k 个字符
reverse(arr, 0, k - 1);
// 反转剩下的字符
reverse(arr, k, n - 1);
return arr.join('');
}
function reverse(arr, start, end) {
while (start < end) {
[arr[start], arr[end]] = [arr[end], arr[start]];
start++;
end--;
}
}
// 测试
const s = "abcdefg";
const k = 2;
console.log(rightRotateString(s, k)); // 输出: "fgabcde"
解释
-
反转整个字符串:
reverse(arr, 0, n - 1)将整个字符串反转。- 例如,
"abcdefg"变成"gfedcba"。
-
反转前
k个字符:reverse(arr, 0, k - 1)将前k个字符反转。- 例如,
"gfedcba"变成"fgedcba"。
-
反转剩下的字符:
reverse(arr, k, n - 1)将剩下的字符反转。- 例如,
"fgedcba"变成"fgabcde"。
解法二:拼接字符串法
- 将字符串分成两部分:前
n - k个字符和后k个字符。 - 将后
k个字符拼接到前n - k个字符的前面。
这种方法的时间复杂度是 O(n),空间复杂度是 O(n)。
代码实现
function rightRotateString(s, k) {
if (!s || s.length === 0 || k <= 0) {
return s;
}
const n = s.length;
k = k % n; // 处理 k 大于字符串长度的情况
// 获取后 k 个字符
const suffix = s.slice(-k);
// 获取前 n - k 个字符
const prefix = s.slice(0, n - k);
// 拼接字符串
return suffix + prefix;
}
// 测试
const s = "abcdefg";
const k = 2;
console.log(rightRotateString(s, k)); // 输出: "fgabcde"
解释
-
获取后
k个字符:s.slice(-k)获取字符串的最后k个字符。- 例如,
"abcdefg".slice(-2)得到"fg"。
-
获取前
n - k个字符:s.slice(0, n - k)获取字符串的前n - k个字符。- 例如,
"abcdefg".slice(0, 5)得到"abcde"。
-
拼接字符串:
suffix + prefix将后k个字符拼接到前n - k个字符的前面。- 例如,
"fg" + "abcde"得到"fgabcde"。
这两种方法都可以有效地解决右旋字符串的问题。选择哪种方法取决于具体的需求和性能考虑。希望这些解释和示例对你有所帮助!如果各位jym有更多问题和其他解法,欢迎在评论区里提问和分析。