题一:反转字符串
题目链接:反转字符串
解题思路: 想都不用想,有两种解题方法,一种是将这个字符串倒序输出到另外一个字符串,另外一个就是使用双指针,这种办法的空间复杂度为o(1),双指针的思路是,让一个left指向开头,一个right指向结尾,然后遍历呼唤,当left不小于right的时候就反转成功了。
解题代码:
// 使用双指针法
var reverseString = function(s) {
let i = 0;
let j = s.length -1;
while(i<=j){
let temp = s[i];
s[i] = s[j];
s[j] = temp;
i++;
j--;
}
};
题二:反转字符串二
题目链接:反转字符串二
解题思路: 关于这一题主要就是要弄清楚题目要求,关键点在于对剩余元素的处理。
解题代码:
var reverse = function (left, right, str) {
// 左闭右开
right = right - 1;
let strArr = str.split('');
while (left < right) {
let temp = strArr[left];
strArr[left] = strArr[right];
strArr[right] = temp;
left++;
right--;
}
str = strArr.join('');
return str;
}
var reverseStr = function (s, k) {
for (let i = 0; i < s.length; i += 2 * k) {
console.log(i)
let extra = s.length - i;
if (extra < k) {
s = reverse(i, s.length, s);
return s;
} else if (extra >= k && extra < 2 * k) {
s = reverse(i, i + k, s)
return s;
} else if (extra >= 2 * k) {
s = reverse(i, i + k, s);
console.log(s)
}
}
return s;
};
题三:替换空格
题目链接:替换空格
解题思路: 要求把给出字符串中的空格字符串替换成%20,在这里用replace就太没意思了,我在这里使用双指针,从后向前遍历,为什么不从前往后,因为从前往后的话要摆正每一次改变元素后被影响元素的位置,从后开始遍历,在这之前我们要扩充在替换空格后的字符串长度,这个长度怎么计算呢?我们已经知道一个空格替换后要占三个位置,所以算出空格数再乘2就是要扩充的长度。遍历的时候,当left指针指向原字符串末尾,right指向扩充后的字符串的末尾,当left遍历到空格时,right连跳三格,把这三个位置依次赋值0,2,%,left也往前移一位,当遍历到飞空格元素的时候,赋值给right位置,直到空格遍历完成就可以跳出了。
解题代码:
// 双指针法
var replaceSpace = function (s) {
let str_arr = s.split('');
let count = 0;
// 计算空格数量
for (let i = 0; i < s.length; i++) {
if (str_arr[i] == ' ') count++;
}
// 更新新数组
let right = str_arr.length + count * 2 -1;
let left = str_arr.length - 1;
while (count) {
if (str_arr[left] == ' ') {
str_arr[right --] = 0;
str_arr[right --] = 2;
str_arr[right --] = '%';
count--;
left--;
}else{
str_arr[right--] = str_arr[left--]
}
}
return str_arr.join('')
};
题四:反转字符串里的单词
题目链接:反转字符串里的单词
解题思路: 这题主要的麻烦之处就是在去除空格,前后中间都有空格,但是反转后的单词中间还要保留一个空格。根据这个情况,我选择按顺序来清楚空格,采用双指针的方法,一个快指针一个慢指针,fast先遍历,遇到空格如果上一个也是空格或者是fast是第一个位置的话就直接跳过,否则就赋值给slow位置,当slow不是在第一个单词上时,每当fast遍历到一个单词时都要赋上一个空格。去空格的操作完成后,就是resize下字符串的长度,然后再是反转整个字符串,最后反转局部字符串即可。
解题代码:
var reverse = function (left, right, s) {
right = right - 1;
s = s.split('');
while (left < right) {
let temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
return s.join('');
}
var reverseWords = function (s) {
// 移除空格
let slow = 0;
let fast = 0;
s = s.split('');
/* for (let i = 0; i < s.length; i++) {
// 移除开头空格 和 重复空格
if ((i === 0 || s[i - 1] === ' ') && s[i] === ' ') {
i++;
} else {
s[slow++] = s[i];
}
} */
while(fast < s.length){
if ((fast === 0 || s[fast - 1] === ' ') && s[fast] === ' ') {
fast++;
} else {
s[slow++] = s[fast++];
}
}
// 移除末尾元素
s.length = s[slow - 1] === ' ' ? slow - 1 : slow;
s = s.join("");
// 反转整个字符串
s = reverse(0, s.length, s);
// 单个单词反转
let fasts = 0;
let slows = 0;
while (fasts < s.length) {
if (s[fasts] === ' ') {
// 遍历到单个单词的边界时要反转
s = reverse(slows, fasts, s);
fasts++;
slows = fasts;
} else {
fasts++;
}
}
// 反转末尾的单词
s = reverse(slows, s.length, s);
return s;
};
题五:左旋字符串
题目链接: 左旋字符串
解题思路: 一句话,局部反转加整体反转,代码也就一行的事情。
解题代码:
var reverseLeftWords = function (s, n) {
// 局部反转 + 整体反转
return reverse(0,s.length,reverse(n,s.length,reverse(0,n,s)));
};