344 反转字符串
题目链接/文章讲解/视频讲解:https://programmercarl.com/0344.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html
方法一:双指针
/**
* @param {character[]} s
* @return {void} Do not return anything, modify s in-place instead.
*/
var reverseString = function(s) {
let left = 0,right = s.length-1;
while(left < right){
if(s[left] !== s[right]){
let temp = s[left];
s[left] = s[right];
s[right] = temp;
}
left++;
right--;
}
return s;
};
注意:本题一开始声明了s如下{character[]} s
,即s是字符数组,而不是字符串,因此可以直接对其进行修改,如果声明s是字符串,即string
,则在JS中字符串不可改,需要将其转为数组结构再进行操作,可见541题。
541 反转字符串Ⅱ
题目链接/文章讲解/视频讲解:https://programmercarl.com/0541.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2II.html
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
var reverseStr = function(s, k) {
const n = s.length;
const arr = Array.from(s);
//i<n防止i+2k后超出字符串长度
for(let i = 0;i < n;i += 2*k){
//Math,min(i+k,n),此时已经i<n,即后面还剩一些元素,则需要面临以下情况:
//1. i+k<n,即剩下的元素个数足够反转k个元素(无论剩下的是不是2k个元素),此时反转从i到(i+k)-1的元素
//2. i+k >n,即数组中剩下的元素个数不足以反转k个,则将从i到(n-1)的元素全部反转,即反转剩下的所有元素
reverse(arr,i,Math.min(i+k,n) - 1);
}
return arr.join('');
};
const reverse = function(arr,left,right) {
while(left < right){
let temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
注意:
1.本题中for循环里i不是普通的i++,根据题意可知,i每次跳2k个,因此为i += 2*k
2.reverse(arr,i,Math.min(i+k,n) - 1);
Math,min(i+k,n),此时已经i<n,即后面还剩一些元素,则需要面临以下情况:
1. i+k<n,即剩下的元素个数足够反转k个元素(无论剩下的是不是2k个元素),此时反转从i到(i+k)-1的元素
2. i+k >n,即数组中剩下的元素个数不足以反转k个,则将从i到(n-1)的元素全部反转,即反转剩下的所有元素
卡码网 54 替换数字
题目链接/文章讲解:https://programmercarl.com/kama54.%E6%9B%BF%E6%8D%A2%E6%95%B0%E5%AD%97.html
本题一开始我的写法如下:
var replaceNumber = function(s) {
let arr = Array.from(s);
for (let i = 0; i < s.length; i++) {
if (isDigit(arr[i])) {
arr.splice(i, 1, 'n', 'u', 'm', 'b', 'e', 'r');
i += 5;
}
}
return arr.join('');
};
const isDigit = function(char) {
return char >= '0' && char <= '9';
};
想的是利用541题里i可以跳好几步,但是忽略了扩大数组长度的问题。
看了题解写了如下写法(卡码网需要自己写输入输出)
var replaceNumber = function(s) {
//统计字符串中数字的个数,以便扩展字符串
let arr = Array.from(s);
let count = 0;
for (let i = 0; i < s.length; i++) {
if (arr[i] >= '0' && arr[i] <= '9') {
count++;
}
}
//扩展数组
arr.length = s.length + count * 5;
for(let i = arr.length - 1,j = s.length - 1;j < i;i--,j--){
if(arr[j] > '9' || arr[j] < '0'){
arr[i] = arr[j];
}else{
arr[i] = 'r';
arr[i - 1] = 'e';
arr[i - 2] = 'b';
arr[i - 3] = 'm';
arr[i - 4] = 'u';
arr[i - 5] = 'n';
i -= 5;
}
}
return arr.join('');
};
let input = "1";
let output = replaceNumber(input);
console.log(output); //number
注意:
1.本题是双指针,且从后向前填充
2.JS中要对字符串进行处理的话,得先转成数组
很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:
1.不用申请新数组。
2.从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
151 翻转字符串里的单词
题目链接/文章讲解/视频讲解:https://programmercarl.com/0151.%E7%BF%BB%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D.html
方法一:双指针
1、移除多余空格(需特殊处理开头和结尾的空格)
2、翻转整个字符串
3、翻转每个单词
本方法融合了数组中移除元素的方法,也融合了翻转字符串的方法。
翻转主要是要确定好开始和末尾的两个位置,明确条件。
翻转单词和删除多余空格那里重点理解。
/**
* @param {string} s
* @return {string}
*/
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];
slowIndex++;
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--;
}
}
方法二:双指针
解题思路:(来自力扣题解:夜剑剑)
使用双指针的方法,从后向前遍历字符
右端的指针遇到空格跳过,直到单词的末尾,然后将左端的指针指向右端
在2的基础上,左指针继续向前,直到遇到空格或小于0才停下(此时左右指针之间就是单词)
把单词添加到结果字符串中,然后把右指针指向左指针,开始下一轮遍历
下一轮遍历开始后,如果还有新单词,就给上一个单词后面添加一个空格
var reverseWords = function (s) {
let r = s.length - 1, l = r, res = "";
while (l >= 0) {
//先找到单词的尾部
while (s[r] === " ") {
r--;
}
l = r;
//给上次单词加空格,排除第一次
if (l >= 0 && res) {
res += " ";
}
//再找到单词的头部
while (s[l] && s[l] !== " ") {
l--;
}
//遍历单词并添加
for (let i = l + 1, j = r; i <= j; i++) {
res += s[i];
}
//跳到下一个单词
r = l;
}
return res;
};
卡码网 55 右旋转字符串
题目链接/文章讲解:
https://programmercarl.com/kama55.%E5%8F%B3%E6%97%8B%E5%AD%97%E7%AC%A6%E4%B8%B2.html
var reverse = function(arr,i,j){
while(i < j){
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
var rightReverse = function(s,k){
let arr = Array.from(s);
//整体翻转
reverse(arr,0,s.length-1);
//前k个翻转
reverse(arr,0,k-1);
//后面的再翻转
reverse(arr,k,s.length-1);
return arr.join('');
}
let str = "abcdefg";
let k = 2;
let output = rightReverse(str,k);
console.log(output);
总结:字符串这里翻转字符串用到的频率很高,各种花式翻转~