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

63 阅读2分钟

344.反转字符串

344.反转字符串

解题思路🤔

1、打基础的时候,不要太迷恋于库函数。 2、使用双指针(即索引下标),同时从两端向中间移动并交换元素。

代码⌨️

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

解题思路🤔

1、有规律的一段一段处理字符串,应在for循环表达式上多思考。

代码⌨️

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("");
};

剑指Offer 05.替换空格

剑指Offer 05.替换空格

解题思路🤔

1、双指针法
2、第一步将数组扩充到每个空格都替换后的大小。
3、从后向前替换空格。i指向新长度的末尾,j指向旧长度的末尾。

代码⌨️

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;
  let right = strArr.length + count * 2 - 1;

  while(left >= 0) {
    if (strArr[left] === ' ') {
      strArr[right--] = '0';
      strArr[right--] = '2';
      strArr[right--] = '%';
      left--;
    } else {
      strArr[right--] = strArr[left--];
    }
  }

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

相关题目🧐

双指针相关


151.翻转字符串里的单词

151.翻转字符串里的单词

解题思路🤔

难度提升! 不要使用辅助空间,空间复杂度要求为O(1)

局部反转 + 整体反转

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

代码⌨️

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

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

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

解题思路🤔

难度提升! 不能申请额外空间,只能在本串上操作

局部反转 + 整体反转

  • 反转区间为前n的子串
  • 反转区间为n到末尾的子串
  • 反转整个字符串

代码⌨️

//不在原字符上操作
var reverseLeftWords = function(s, n) {
  const length = s.length;
  let i = 0;
  while (i < length - n) {
    s = s[length - 1] + s;
    i++;
  }
  return s.slice(0, length);
};


//在原字符上操作
var reverseLeftWords = function (s, n) {
    /** Utils */
    function reverseWords(strArr, start, end) {
        let temp;
        while (start < end) {
            temp = strArr[start];
            strArr[start] = strArr[end];
            strArr[end] = temp;
            start++;
            end--;
        }
    }
    /** Main code */
    let strArr = s.split('');
    let length = strArr.length;
    reverseWords(strArr, 0, length - 1);
    reverseWords(strArr, 0, length - n - 1);
    reverseWords(strArr, length - n, length - 1);
    return strArr.join('');
};