344.反转字符串
题目链接:344.反转字符串
文档讲解:代码随想录/反转字符串
视频讲解:视频讲解-反转字符串
状态:已完成(1遍)
解题过程
看到题目的第一想法
我的第一想法是双指针,一左一右两个指针,指向的字母调换位置。
/**
* @param {character[]} s
* @return {void} Do not return anything, modify s in-place instead.
*/
var reverseString = function(s) {
if(s.length == 1) return s;
let left = 0,right = s.length -1;
while(left<right){
[s[left],s[right]] = [s[right],s[left]]
left++;
right--;
}
return s;
};
提交没有问题,来看看代码随想录怎么说。
看完代码随想录之后的想法
这道题还是比较简单的,反转的思维跟数组里的有序数组的平方和比较类似。
不过文字讲解的答案看上去还是比较简洁:
/**
* @param {character[]} s
* @return {void} Do not return anything, modify s in-place instead.
*/
var reverseString = function(s) {
//Do not return anything, modify s in-place instead.
reverse(s)
};
var reverse = function(s) {
let l = -1, r = s.length;
while(++l < --r) [s[l], s[r]] = [s[r], s[l]];
};
总结
这道题总的来说跟操作数组没有什么区别,较为简单。
541.反转字符 II
题目链接:541.反转字符 II
文档讲解:代码随想录/反转字符 II
视频讲解:视频讲解-反转字符串 II
状态:已完成(1遍)
解题过程
看到题目的第一想法
剩余字符有三种情况,那就在for循环里来三个if,每种的处理情况不同,但反转的部分都类似,把要反转的部分取出,反转,再放回去。
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
var reverseStr = function(s, k) {
const sArr = s.split('');
let len = sArr.length;
for(let i = 0;i<len;){
if(len<i+k){
let sliceArr = sArr.slice(i,len).reverse();//把要反转的部分切出来,再反转一下
sArr.splice(i,len-i,...sliceArr);//再把反转好的部分给替换掉
i = len;
}else if(len>=i+k&&len<i+2*k){
let sliceArr = sArr.slice(i,i+k).reverse();
sArr.splice(i,k,...sliceArr);
i = len;
}else if(len>=i+2*k){
let sliceArr = sArr.slice(i,i+k).reverse();
sArr.splice(i,k,...sliceArr);
i+=2*k;
}
}
let ans = sArr.join('');
return ans;
};
提交也没有问题,继续看看代码随想录。
看完代码随想录之后的想法
步骤怎么这么短,哥们错付了。。。
确实不用对剩余字符小于2k但大于k个的情况和大于2k的情况做区分,两者都是要反转前k个字符串的,而我也忘记了我最爱的?:可以在这里用上,两种情况只有reverse的长度需要区分,这样判断起来确实更快一些。这样的用法搭配上不用reverse的初始写法甚至更简便。
讲解代码如下:
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
var reverseStr = function(s, k) {
const len = s.length;
let resArr = s.split("");
for(let i = 0; i < len; i += 2 * k) { // 每隔 2k 个字符的前 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("");
};
总结
像这题一样,成段成段的往后跳的话,for循环的i可以不用i++,而是也跟这着段的跳。同时善用条件运算符。
卡码网:54.替换数字
题目链接:卡码网:54.替换数字
文档讲解:代码随想录/卡码网·替换数字
视频讲解:无
状态:已完成(1遍)
解题过程
看到题目的第一想法
拆成数组,遍历,有数字就把它换成"number",最后再转换成字符串。
不是哥们,一通操作猛如虎,输入完了运行告诉我没登录不给运行,登录完了之后我代码没了????
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
function main() {
const num0 = "0".charCodeAt();
const num9 = "9".charCodeAt();
const a = "a".charCodeAt();
const z = "z".charCodeAt();
function isAZ(str) {
return str >= a && str <= z;
}
function isNumber(str) {
return str >= num0 && str <= num9;
}
rl.on("line", (input) => {
const inputArr = input.split("");
for (let i = 0; i < inputArr.length; i++) {
let ascii = input[i].charCodeAt();
if (isNumber(ascii)) {
inputArr[i] = "number";
}
}
console.log(inputArr.join(""));
})
}
main();
运行提交都没问题。
看完代码随想录之后的想法
真的需要这样写吗,直接把数组里的数字改成“number”应该也没有任何问题吧?有没有大神能解答一下。
讲解代码如下:
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
function main() {
const num0 = "0".charCodeAt();
const num9 = "9".charCodeAt();
const a = "a".charCodeAt();
const z = "z".charCodeAt();
function isAZ(str) {
return str >= a && str <= z;
}
function isNumber(str) {
return str >= num0 && str <= num9;
}
rl.on("line", (input) => {
let n = 0;
for (let i = 0; i < input.length; i++) {
const val = input[i].charCodeAt();
if (isNumber(val)) {
n+= 6;
}
if (isAZ(val)) {
n++;
}
}
const ans = new Array(n).fill(0);
let index = input.length - 1;
for (let i = n - 1; i >= 0; i--) {
const val = input[index].charCodeAt();
if (isAZ(val)) {
ans[i] = input[index];
}
if (isNumber(val)) {
ans[i] = "r";
ans[i - 1] = "e";
ans[i - 2] = "b";
ans[i - 3] = "m";
ans[i - 4] = "u";
ans[i - 5] = "n";
i -= 5;
}
index--;
}
console.log(ans.join(""));
})
}
main();
总结
这道题属实是没有想到用到双指针上面去,不过也算是学习了一种思路了。
151.翻转字符串里的单词
题目链接:151.翻转字符串里的单词
文档讲解:代码随想录/翻转字符串里的单词
视频讲解:视频讲解-翻转字符串里的单词
状态:已完成(1遍)
解题过程
看到题目的第一想法
来个双指针,一左一右往中间夹,遇到空字符串就把它删了,只有左右指针指向的值都不是空字符串的时候才交换两指针的值。
/**
* @param {string} s
* @return {string}
*/
var reverseWords = function(s) {
const sArr = s.split(" ");
let len = sArr.length;
let left = 0,right = len-1;
while(left<right){
while(sArr[left]=="") sArr.splice(left,1);
while(sArr[right]=="")sArr.splice(right,1);
[sArr[left],sArr[right]] = [sArr[right],sArr[left]];
left++;
right--;
}
const ans = sArr.join(" ");
return ans;
};
直接当小丑,运行都通不过,debug了一波又一波,发现了如下问题:
- 如果查到空字符串,left可以splice,但是同时right也得--;同样right这边如果splice了的话也得--;
- 如果最后指针在中间是几个空字符串,那么会让最中间的已经交换过的再交换回来;
- 如果left和right相等了,但是最后相等的时候是个空字符串,得把他删掉。
修改后的代码如下:
/**
* @param {string} s
* @return {string}
*/
var reverseWords = function (s) {
const sArr = s.split(" ");
let len = sArr.length;
let left = 0, right = len - 1;
while (left < right) {
while (sArr[left] == "") {
sArr.splice(left, 1);
right--;//注意这里要及时将right减一
}
while (sArr[right] == "") {
sArr.splice(right, 1);
right--;//注意这里要及时将right减一
};
if (left < right) {
[sArr[left], sArr[right]] = [sArr[right], sArr[left]];
left++;
right--;
}
}
if(left==right&&sArr[left]=="") sArr.splice(left,1)
const ans = sArr.join(" ");
return ans;
};
提交终于没问题了。。。debug了半小时。。。
看完代码随想录之后的想法
卡哥的思想是去除多余的空格,翻转字符串,再翻转单词,确实也是学到了新思路。
/**
* @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++];
}
}
// 移除末尾空格
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--;
}
}
总结
我感觉这道题还是我自己想出来的思路比较容易理解一点哈哈,不过先翻转所有字符串再反转单词内的字符串也很牛逼。