代码随想录算法训练营第八天|344.反转字符串 541. 反转字符串II 卡码网:54.替换数字 151.翻转字符串里的单词 卡码网:55.右旋转字符串(JS写法)

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);

总结:字符串这里翻转字符串用到的频率很高,各种花式翻转~

  • 35
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值