文章目录
代码随想录算法训练营第【X】天 | 【题目名】、【题目名】、【题目名】
LeetCode 344.反转字符串
题目链接🔗:344.反转字符串
解题思路🤔
reverse
方法的实现,没啥好说的。
遇到的问题😢
无
代码实现👨🏻💻
var reverseString = function(s) {
let left = 0,
right = s.length - 1;
while(left < right) {
const temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
};
总结📖
卡哥提醒,如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。如果库函数仅仅是解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。
LeetCode 541. 反转字符串II
题目链接🔗:541. 反转字符串II
解题思路🤔
思路是在遍历循环中每次让i
前进2k
个位置,再反转前k
个字符。
遇到的问题😢
代码实现👨🏻💻
var reverseStr = function(s, k) {
const len = s.length;
let resArr = s.split(""); // 串s转换为字符串数组
for (let i = 0; i < len; i += 2 * k) { // i每次移动2k个位置
let left = i, // i每次移动的次数不为1,不能用i++,要让left = i,这样left指针每次才能移动2k个位置
right = i + k > len ? len : i + k; // i + k比len大,直接让right指向len的位置;否则right指向i + k位置,表示前k个字符
reverse(resArr, left, right - 1); // right - 1是因为此时right的位置是尾元素之后,需要-1使其回到尾元素身上
}
return resArr.join(""); // 字符串数组resArr转换为串
};
var reverse = function(arr, left, right) { // 自己定义一个reverse,直接用reverse()方法也可以
while(left < right) {
const temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
};
总结📖
注意对right
指针的判断,对元素所在位置时刻保持清醒。
LeetCode 剑指Offer 05.替换空格
题目链接🔗:剑指Offer 05.替换空格
解题思路🤔
思路是将串转化为数组,然后通过计算数组中元素的个数可以得到原串中空格的数量,随后重新拼接数组,将每个数组元素之间插入一个"20%",最后再转换为字符串即可。
需要注意的是,数组在定义后是长度固定的,因此在向一个存满的数组中插入元素时需要扩充数组,而扩充的大小是空格数量的两倍,因为一个空格本身占一位,我们替换后是占三位,所以再添加两位即可。
遇到的问题😢
无
代码实现👨🏻💻
var replaceSpace = function (s) {
const strArr = Array.from(s); // 字符串转换为数组
let count = 0; // 用于统计空格的数量
// 计算空格数量
for (let i = 0; i < strArr.length; i++) {
if (strArr[i] === " ") count++;
}
let left = strArr.length - 1, // left指向数组尾元素位置
right = strArr.length + count * 2 - 1; // right指向数组尾元素后 2 * count位置,扩充数组
while (left >= 0) {
if (strArr[left] === " ") { // 插入%20,因为是从后向前插入,所以顺序为0->2->%
strArr[right--] = "0";
strArr[right--] = "2";
strArr[right--] = "%";
left--; // 插入后left左移,寻找下一个插入点
} else {
strArr[right--] = strArr[left--]; // 在尾元素处未找到插入点,就不用扩充数组了
}
}
return strArr.join(""); // 数组转字符串
};
总结📖
需要注意数组需要扩充,以及扩充多少的问题。
LeetCode 151.翻转字符串里的单词
题目链接🔗:151.翻转字符串里的单词
解题思路🤔
- 移除多余的空格
- 将整个字符串反转
- 将每个单词反转
遇到的问题😢
一开始使用spilt做完,发现卡哥说这样做就没意义了。。。看了卡哥思路后完成。
代码实现👨🏻💻
var reverseWords = function(s) {
// 字符串转数组
const strArr = Array.from(s);
// 移除多余空格
removeExtraSpaces(strArr);
// 翻转
reverse(strArr, 0, strArr.length - 1);
let start = 0;
for(let i = 0; i <= strArr.length; i++) {
if (strArr[i] === ' ' || i === strArr.length) {
// 翻转单词
reverse(strArr, start, i - 1);
start = i + 1;
}
}
return strArr.join('');
};
// 删除多余空格
function removeExtraSpaces(strArr) {
let slowIndex = 0;
let fastIndex = 0;
while(fastIndex < strArr.length) {
// 移除开始位置和重复的空格
if (strArr[fastIndex] === ' ' && (fastIndex === 0 || strArr[fastIndex - 1] === ' ')) {
fastIndex++;
} else {
strArr[slowIndex++] = strArr[fastIndex++];
}
}
// 移除末尾空格
strArr.length = strArr[slowIndex - 1] === ' ' ? slowIndex - 1 : slowIndex;
};
// 翻转从 start 到 end 的字符
function reverse(strArr, start, end) {
let left = start;
let right = end;
while(left < right) {
// 交换
[strArr[left], strArr[right]] = [strArr[right], strArr[left]];
left++;
right--;
}
};
总结📖
用双指针法比使用库函数更好。
LeetCode 剑指Offer58-II.左旋转字符串
题目链接🔗:剑指Offer58-II.左旋转字符串
解题思路🤔
- 反转区间为前n的子串
- 反转区间为n到末尾的子串
- 反转整个字符串
遇到的问题😢
无
代码实现👨🏻💻
var reverseLeftWords = function (s, n) {
let strArr = s.split(''); // 转换为字符串数组
let length = strArr.length;
reverseWords(strArr, 0, length - 1); // 反转整个数组
reverseWords(strArr, 0, length - n - 1); // 反转前n项
reverseWords(strArr, length - n, length - 1); // 反转n到末尾
return strArr.join(''); // 转换为字符串
};
var reverseWords = function (strArr, start, end) {
let temp;
while (start < end) {
temp = strArr[start];
strArr[start] = strArr[end];
strArr[end] = temp;
start++;
end--;
}
};
总结📖
需要注意的是转换为数组后需要先全部反转,不然会出问题
今日收获
- 字符串的题目还是比较好想的,注意细节。
- 如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数;如果库函数仅仅是解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。
- 刷题时间越来越不够用啦,少摸鱼,多做题!