Leetcode 344.反转字符串

题目:344.反转字符串

初始思路

简单解法就是直接调用字符串的reverse方法。
但是如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。
这题使用双指针即可,从头和尾开始往中间夹

代码

  1. var reverseString = function (s) {
  2. var temp
  3. var n = s.length
  4. for (let i = 0; i < Math.ceil(n / 2); i++) {
  5. temp = s[i]
  6. s[i] = s[n - 1 - i]
  7. s[n - 1 - i] = temp
  8. }
  9. };
  10. // 二刷
  11. var reverseString = function (s) {
  12. let left = 0, right = s.length - 1
  13. while (left < right) {
  14. [s[left], s[right]] = [s[right], s[left]]
  15. left++
  16. right--
  17. }
  18. }

感想

  1. 常规题,控制住自己不要使用reverse函数

Leetcode 541.反转字符串II

题目:541.反转字符串II

初始思路

直接按照题目的思路写就行,没有什么出彩的思路。

代码

  1. var reverse = function (arr, left, right) {
  2. while (left < right) {
  3. [arr[left], arr[right]] = [arr[right], arr[left]]
  4. left++
  5. right--
  6. }
  7. }
  8. var reverseStr = function (s, k) {
  9. const n = s.length
  10. let arr = s.split('');
  11. console.log(arr);
  12. for (let i = 0; i < n; i += 2 * k) {
  13. // 判断i+k会不会小于数组长度,取两者更小值
  14. reverse(arr, i, Math.min(i + k, n) - 1)
  15. }
  16. return arr.join('')
  17. };

感想

  1. reverse函数名被我写错了,直接写成递归了。直接爆栈,纯纯无语。
  2. 上一题的反转字符串在这里就能用到了。
  3. 主要就是在反转的时候传参,如果i+k超过了数组的长度,也就是说剩余部分不足k的话,全部反转。

剑指Offer 05.替换空格

题目:剑指Offer 05.替换空格 讲解:代码随想录

初始思路

replace函数只能替换第一次出现的字符,如果需要全部替换需要使用正则表达式。
看了一下代码随想录,原来和数组扩容有关。

代码

  1. // 正则表达式
  2. var replaceSpace = function (s) {
  3. let reg = new RegExp(' ', 'g')
  4. return s.replace(reg, '%20')
  5. };
  1. // 数组扩容
  2. var replaceSpace = function (s) {
  3. // 从s转换一个数组
  4. const strArr = Array.from(s)
  5. let count = 0
  6. // 计算空格数量
  7. for (let i = 0; i < strArr.length; i++) {
  8. if (strArr[i] === ' ') count++
  9. }
  10. // left指向原字符串的最后一个字符
  11. let left = strArr.length - 1
  12. // 需要把空格换成%20,比起之前每个空格还需要两个位置
  13. // right指向扩容后的数组最后一位
  14. let right = strArr.length + count * 2 - 1
  15. // 从后向前替换空格,也就是双指针法
  16. while (left >= 0) {
  17. if (strArr[left] === ' ') {
  18. // 倒着填充
  19. strArr[right--] = '0'
  20. strArr[right--] = '2'
  21. strArr[right--] = '%'
  22. // left指针继续向前寻找空格
  23. left--
  24. } else {
  25. // 如果没遇到空格,把这个元素复制到扩容的部分
  26. strArr[right--] = strArr[left--]
  27. }
  28. }
  29. return strArr.join('')
  30. }

感想

  1. 第一反应就是正则表达式,很简便。
  2. 没想到这题的考点是数组扩容,还是有点复杂的,尤其是从后面开始填充很精妙,如果从前面开始替换的话,数组元素需要不停的移动。

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

题目:151.翻转字符串里的单词 讲解:代码随想录

初始思路

第一反应是去除多余空格,然后用split分隔,最后倒序相加即可。
看了一下代码随想录,说这个想法会让题目变成水题,要用正经解法。

代码

  1. // 正则表达式
  2. var reverseWords = function (s) {
  3. return s.trim().split(/\s+/).reverse().join(' ');
  4. };
  1. // 正攻
  2. // 删除多余的空格
  3. var removeExtraSpaces = function (strArr) {
  4. let slow = 0;
  5. let fast = 0;
  6. while (fast < strArr.length) {
  7. // 移除开始位置和重复的空格
  8. if (strArr[fast] === ' ' && (fast === 0 || strArr[fast - 1] === ' ')) {
  9. fast++;
  10. } else {
  11. strArr[slow++] = strArr[fast++];
  12. }
  13. }
  14. // 移除末尾空格
  15. strArr.length = strArr[slow - 1] === ' ' ? slow - 1 : slow;
  16. }
  17. // 翻转字符
  18. var reverse = function (strArr, start, end) {
  19. let left = start
  20. let right = end
  21. while (left < right) {
  22. [strArr[left], strArr[right]] = [strArr[right], strArr[left]]
  23. left++
  24. right--
  25. }
  26. }
  27. var reverseWords = function (s) {
  28. // 字符串转数组
  29. const strArr = Array.from(s)
  30. // 去除空格
  31. removeExtraSpaces(strArr)
  32. // 从头到尾翻转
  33. reverse(strArr, 0, strArr.length - 1)
  34. let index = 0
  35. for (let i = 0; i <= strArr.length; i++) {
  36. if (strArr[i] === ' ' || i === strArr.length) {
  37. // 翻转每个单词
  38. reverse(strArr, index, i - 1)
  39. index = i + 1
  40. }
  41. }
  42. return strArr.join('')
  43. }

感想

  1. 正则表达式依旧很简便。
  2. 删除空格的操作有些复杂。
  3. 在确定字符的时候要注意for循环 i<=strArr.length。当找到一个空格的时候,开始翻转前面的字符,开始位置用index标记,结束位置是i-1。

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

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

初始思路

使用字符串截取和替换可以很简单的做到。
思路二:可以先整体翻转,然后在中断的地方左右两边分别翻转。

代码

  1. // 使用库函数
  2. var reverseLeftWords = function (s, n) {
  3. let sub = s.slice(0, n)
  4. let str = s.replace(sub, '') + sub
  5. return str
  6. };
  1. // 正攻
  2. // 翻转字符
  3. var reverse = function (strArr, start, end) {
  4. let left = start
  5. let right = end
  6. while (left < right) {
  7. [strArr[left], strArr[right]] = [strArr[right], strArr[left]]
  8. left++
  9. right--
  10. }
  11. }
  12. var reverseLeftWords = function (s, n) {
  13. const len = s.length
  14. const strArr = Array.from(s)
  15. // 整个翻转
  16. reverse(strArr, 0, len - 1)
  17. // 左部分翻转
  18. reverse(strArr, 0, len - n - 1)
  19. // 右部分翻转
  20. reverse(strArr, len - n, len - 1)
  21. return strArr.join('')
  22. }

感想

  1. 和上一题151.翻转字符串里的单词有相似的思路。
  2. 这个翻转指定位置的函数要熟练掌握。
  3. 万物归于双指针!