字符串
344、反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[]
的形式给出。
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
var reverseString = function(s) { // return s.reverse(); let l = -1, r = s.length; while(++l < --r) [s[l], s[r]] = [s[r], s[l]]; return s; };
541、反转字符串||
给定一个字符串 s
和一个整数 k
,从字符串开头算起,每 2k
个字符反转前 k
个字符。
- 如果剩余字符少于
k
个,则将剩余字符全部反转。 - 如果剩余字符小于
2k
但大于或等于k
个,则反转前k
个字符,其余字符保持原样。
输入:s = "abcdefg", k = 2 输出:"bacdfeg"
输入:s = "abcd", k = 2 输出:"bacd"
思路:当需要固定规律一段一段去处理字符串的时候,要想想for循环的表达式---遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
var reverseStr = function(s, k) { const len = s.length; let resArr = s.split(""); for(let i = 0; i < len; i += 2 * 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(""); };
151、翻转字符串里的单词
给你一个字符串 s
,逐个翻转字符串中的所有 单词 。单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。请你返回一个翻转 s
中单词顺序并用单个空格相连的字符串。
- 输入字符串
s
可以在前面、后面或者单词间包含多余的空格。 - 翻转后单词间应当仅用一个空格分隔。
- 翻转后的字符串中不应包含额外的空格。
输入:s = "the sky is blue
"
输出:"blue is sky the
"
输入:s = " hello world "
输出:"world hello"
思路:移除多余空格;将整个字符串反转;将每个单词反转
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、左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
输入: s = "abcdefg", k = 2 输出: "cdefgab"
输入: s = "lrloseumgh", k = 6 输出: "umghlrlose"
思路:反转区间为前n的子串;反转区间为n到末尾的子串;反转整个字符串
var reverseLeftWords = function(s, n) { const reverse = (str, left, right) => { let strArr = str.split(""); for (; left < right; left++, right--) { [strArr[left], strArr[right]] = [strArr[right], strArr[left]]; } return strArr.join(""); } s = reverse(s, 0, n - 1); s = reverse(s, n, s.length - 1); return reverse(s, 0, s.length - 1); };
剑指Offer 05.替换空格
请实现一个函数,把字符串 s
中的每个空格替换成"%20"
输入:s = "We are happy." 输出:"We%20are%20happy."
思路:首先扩充数组到每个空格替换成"%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; 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(''); };
很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前先后填充元素导致的每次添加元素都要将添加元素之后的所有元素向后移动。