【前端er每日算法】字符串5题

98 阅读1分钟

题目一 344. 反转字符串

思路

太简单,直接上代码,没啥可说

var reverseString = function(s) {
    let i = 0;
    let j = s.length - 1;
    while (i < j) {
        let tmp = s[j];
        s[j--] = s[i];
        s[i++] = tmp;
    }
    return s;
};

题目2 541. 反转字符串 II

思路

写了很纠结的代码,很久很久就是写不对,每次这种情况就会质疑自己,最后看了解题,很清晰很简洁。

官方思路是每次走2k,然后反转前k个,如果最后的不足k个,要注意取边界,min(i + k - 1, n - 1), 否则就出界错误了。

我写的每次走k步,记录奇偶,偶数次数反转,否则不反转,这种更麻烦啊。不如官方答案好,这就是差距吧。

var reverseString = function(s, i, j) {
    while (i < j) {
        let tmp = s[j];
        s[j--] = s[i];
        s[i++] = tmp;
    }
    return s;
};

var reverseStr = function(s, k) {
    let len = s.length;
    s = s.split('');
    let isOdd = true;
    let i = 0;
    for (i = 0; i < len; i += k) {
        if (isOdd) {
            let min = Math.min(i + k - 1, len - 1);
            s = reverseString(s, i, min);
            // console.log(s,i,i+k);
        }
        isOdd = !isOdd
    }
    return s.join('');
};

上面的写法不够简洁清晰,又写了一遍

function reverse(arr, left, right) {
 while (left < right) {
     [arr[left], arr[right - 1]] = [arr[right - 1], arr[left]]
     left++;
     right--;
 }
}
var reverseStr = function(s, k) {
    const len = s.length;
    const arr = s.split('');
    const step = 2 * k;
    // 每2k走一步,前k个反转,如果不足k个,则将剩余的全部翻转
    for (let i = 0; i < len; i += step) {
        if (i + k < len) {
            reverse(arr, i, i + k);
        } else {
            reverse(arr, i, len);
        }
    }
    return arr.join('')
};

题目3 剑指 Offer 05. 替换空格

思路

忽然来这么简单的题,有点不适应,这里注意的就是js中字符串没办法通过索引来修改,所以需要先改为字符数组,这样修改其中的字符。

image.png

var replaceSpace = function(s) {
    s = s.split('');
    for (let i = 0; i < s.length; i++) {
        if (s[i] === ' ') {
            s[i] = '%20';
        }
    }
    return s.join('')
};

题目4 151. 反转字符串中的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入:s = "the sky is blue" 输出:"blue is sky the"

思路

  1. 反转整个字符串
  2. 再反转每个单词得到最后的字符串

整体思路如上,但是需要先删除空格,参考删除数组中元素的方法,使用快慢指针删除,当fast遇到不等于' '的字符时,说明是一个单词的开始,然后如果slow不是第一个元素,则手动补充空字符串,遍历当前单词,fast赋值slow,直到fast走到结尾。

删除完空格后就按照上面的逻辑来反转字符串。

 var reverseString = function(s, i, j) {
    while (i < j) {
        let tmp = s[j];
        s[j--] = s[i];
        s[i++] = tmp;
    }
    return s;
};

var strip = function(s) {
    let len = s.length;
    let i = 0;
    // 先删除空格
    for (let j = 0; j < len; j++) {
        if (s[j] !== ' ') {
            if (i > 0) {
                s[i++] = ' '
            }
            while (s[j] !== ' ' && j < len) {
                s[i++] = s[j++];
            }
        }
    }
    return i;
};

var reverseWords = function(s) {
    let arr = s.split('');
    // 先删除空格, 返回了新的串的长度
    let len = strip(arr);
    reverseString(arr, 0, len - 1);
    let start = 0;
    for (let i = 0; i < len; i++) {
        start = i;
        while(arr[i] !== ' ' && i < len) {
            i++;
        }
        reverseString(arr, start, i - 1);
    }
    return arr.slice(0, len).join('')
};

题目5 剑指 Offer 58 - II. 左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:

输入: s = "abcdefg", k = 2
输出: "cdefgab"

思路

  1. 反转前k后
  2. 反转k到len-1的字符串
  3. 反转整个字符串

代码

 var reverseString = function(s, i, j) {
    while (i < j) {
        let tmp = s[j];
        s[j--] = s[i];
        s[i++] = tmp;
    }
    return s;
};

/**
 * @param {string} s
 * @param {number} n
 * @return {string}
 */
var reverseLeftWords = function(s, n) {
    const arr = s.split('')
    reverseString(arr, 0, n - 1);
    reverseString(arr, n, s.length - 1);
    reverseString(arr, 0, s.length - 1);
    return arr.join('')
};