建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数
题目链接/文章讲解/视频讲解:代码随想录
先看文章学习思路:对于字符串,我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。
var reverseString = function(s) {
for (let i = 0, j = s.length - 1; i < s.length/2; i++, j--) {
let tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
};
541. 反转字符串II
建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
题目链接/文章讲解/视频讲解:代码随想录
知识点1:
在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。因为要找的也就是每2 * k 区间的起点。
所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
知识点2:学会js中反转字符串方式
知识点3:判断剩余字符的个数,用三元表达式
var reverseStr = function(s, k) {
const len = s.length;
let resArr = s.split("");
for(let i=0;i<len; i += (2 * k)){
//i + k > len 剩余字符少于 k 个,则将剩余字符全部反转。
let l = i - 1, r = i + k > len ? len : i + k;
while(++l < --r)
[resArr[l], resArr[r]] = [resArr[r], resArr[l]];
}
return resArr.join("");
};
剑指Offer 05.替换空格
建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
题目链接/文章讲解:代码随想录
思路
如果想把这道题目做到极致,就不要只用额外的辅助空间了!
首先扩充数组到每个空格替换成"%20"之后的大小。
然后从后向前替换空格,也就是双指针法,过程如下:
i指向新长度的末尾,j指向旧长度的末尾。
有同学问了,为什么要从后向前填充,从前向后填充不行么?
从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素向后移动。
其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前先后填充元素要来的 每次添加元素都要将添加元素之后的所有元素向后移动。
知识点:
字符串转化为数组
// 字符串转为数组
const strArr = Array.from(s);
数组转化为字符串
// 数组转字符串
return strArr.join('');
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;
let right = strArr.length + count * 2 - 1;
while(left>0){
if (strArr[left] === ' ') {
strArr[right--] = '0';
strArr[right--] = '2';
strArr[right--] = '%';
left--;
}else{
strArr[right--] = strArr[left--];
}
}
// 数组转字符串
return strArr.join('');
};
151.翻转字符串里的单词
建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
题目链接/文章讲解/视频讲解:代码随想录
提高一下本题的难度:不要使用辅助空间,空间复杂度要求为O(1)。
所以解题思路如下:
- 移除多余空格
- 将整个字符串反转
- 将每个单词反转
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 str.join('')
};
剑指Offer58-II.左旋转字符串
建议:题解中的解法如果没接触过的话,应该会想不到
题目链接/文章讲解:代码随想录
不能申请额外空间,只能在本串上操作。
这道题目也非常类似,依然可以通过局部反转+整体反转 达到左旋转的目的。
具体步骤为:
- 反转区间为前n的子串
- 反转区间为n到末尾的子串
- 反转整个字符串
最后就可以得到左旋n的目的,而不用定义新的字符串,完全在本串上操作。
自己根据思路单独写出代码
var reverseLeftWords = function(s, n) {
let length=s.length;
const strArr=Array.from(s)
reverse(strArr,0,n-1)
reverse(strArr,n,length-1)
reverse(strArr,0,length-1)
return strArr.join('')
};
function reverse(strArr, start, end) {
let left = start;
let right = end;
while(left < right) {
// 交换
[strArr[left], strArr[right]] = [strArr[right], strArr[left]];
left++;
right--;
}
}
学思路,自己写