代码随想录算法训练营第八天 | 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串

这篇博客记录了作者在算法训练营中解决五道字符串操作题目的过程,包括LeetCode的344.反转字符串、541.反转字符串II、剑指Offer的05.替换空格、151.翻转字符串里的单词和58-II.左旋转字符串。作者强调了解题思路、遇到的问题以及如何避免过度依赖库函数。
摘要由CSDN通过智能技术生成

代码随想录算法训练营第【X】天 | 【题目名】、【题目名】、【题目名】

LeetCode 344.反转字符串

题目链接🔗:344.反转字符串

解题思路🤔

reverse方法的实现,没啥好说的。

遇到的问题😢

代码实现👨🏻‍💻

var reverseString = function(s) {
    let left = 0, 
        right = s.length - 1;

    while(left < right) {
        const temp = s[left];
        s[left] = s[right];
        s[right] = temp;
        
        left++;
        right--;
    }  
};

总结📖

卡哥提醒,如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。如果库函数仅仅是解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。


LeetCode 541. 反转字符串II

题目链接🔗:541. 反转字符串II

解题思路🤔

思路是在遍历循环中每次让i前进2k个位置,再反转前k个字符。

遇到的问题😢

代码实现👨🏻‍💻

var reverseStr = function(s, k) {
    const len = s.length;
    let resArr = s.split(""); // 串s转换为字符串数组
    
    for (let i = 0; i < len; i += 2 * k) { // i每次移动2k个位置
        let left = i, // i每次移动的次数不为1,不能用i++,要让left = i,这样left指针每次才能移动2k个位置
            right = i + k > len ? len : i + k; // i + k比len大,直接让right指向len的位置;否则right指向i + k位置,表示前k个字符
        reverse(resArr, left, right - 1); // right - 1是因为此时right的位置是尾元素之后,需要-1使其回到尾元素身上
    }
    return resArr.join(""); // 字符串数组resArr转换为串
};

var reverse = function(arr, left, right) { // 自己定义一个reverse,直接用reverse()方法也可以
    while(left < right) {
        const temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
        left++;
        right--;
    }
};

总结📖

注意对right指针的判断,对元素所在位置时刻保持清醒。

LeetCode 剑指Offer 05.替换空格

题目链接🔗:剑指Offer 05.替换空格

解题思路🤔

思路是将串转化为数组,然后通过计算数组中元素的个数可以得到原串中空格的数量,随后重新拼接数组,将每个数组元素之间插入一个"20%",最后再转换为字符串即可。

需要注意的是,数组在定义后是长度固定的,因此在向一个存满的数组中插入元素时需要扩充数组,而扩充的大小是空格数量的两倍,因为一个空格本身占一位,我们替换后是占三位,所以再添加两位即可。

遇到的问题😢

代码实现👨🏻‍💻

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, // left指向数组尾元素位置
        right = strArr.length + count * 2 - 1; // right指向数组尾元素后 2 * count位置,扩充数组

    while (left >= 0) {
        if (strArr[left] === " ") { // 插入%20,因为是从后向前插入,所以顺序为0->2->%
            strArr[right--] = "0";
            strArr[right--] = "2";
            strArr[right--] = "%";
            left--; // 插入后left左移,寻找下一个插入点
        } else {
            strArr[right--] = strArr[left--]; // 在尾元素处未找到插入点,就不用扩充数组了
        }
    }

    return strArr.join(""); // 数组转字符串
};

总结📖

需要注意数组需要扩充,以及扩充多少的问题。

LeetCode 151.翻转字符串里的单词

题目链接🔗:151.翻转字符串里的单词

解题思路🤔

  • 移除多余的空格
  • 将整个字符串反转
  • 将每个单词反转

遇到的问题😢

一开始使用spilt做完,发现卡哥说这样做就没意义了。。。看了卡哥思路后完成。

代码实现👨🏻‍💻

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

总结📖

用双指针法比使用库函数更好。


LeetCode 剑指Offer58-II.左旋转字符串

题目链接🔗:剑指Offer58-II.左旋转字符串

解题思路🤔

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串
    在这里插入图片描述

遇到的问题😢

代码实现👨🏻‍💻

var reverseLeftWords = function (s, n) {
    let strArr = s.split(''); // 转换为字符串数组
    let length = strArr.length; 
    reverseWords(strArr, 0, length - 1); // 反转整个数组
    reverseWords(strArr, 0, length - n - 1); // 反转前n项
    reverseWords(strArr, length - n, length - 1); // 反转n到末尾
    return strArr.join(''); // 转换为字符串
};

var reverseWords = function (strArr, start, end) {
    let temp;
    while (start < end) {
        temp = strArr[start];
        strArr[start] = strArr[end];
        strArr[end] = temp;
        start++;
        end--;
    }
};

总结📖

需要注意的是转换为数组后需要先全部反转,不然会出问题


今日收获

  1. 字符串的题目还是比较好想的,注意细节。
  2. 如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数;如果库函数仅仅是解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。
  3. 刷题时间越来越不够用啦,少摸鱼,多做题!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值