LeetCode151 翻转字符串里的单词 & 剑指Offer 58 - I 翻转单词顺序

LeetCode151 翻转字符串里的单词 & 剑指Offer 58 - I 翻转单词顺序

题目

在这里插入图片描述

解题

解题一:使用语言特性

在这里插入图片描述

// javascript
var reverseWords = function(s) {
    return s.trim().split(/\s+/).reverse().join(' ');
};

在这里插入图片描述

解题二:队列

在这里插入图片描述

// javascript
var reverseWords = function(s) {
    const n = s.length;
    let left = 0, right = n - 1;
    while (left <= right && s[left] === ' ') {       // 去掉字符串开头的空白字符
        left++;
    }
    while (left <= right && s[right] === ' ') {      // 去掉字符串末尾的空白字符
        right--;
    }
    let word = [];
    const queue = [];
    while (left <= right) {
        if (s[left] === ' ' && word.length > 0) {    // 如果 left 指向空格但是 word 为空:该空格是多余的
            queue.unshift(word.join(''));            // 将单词拼接插入队列的头部
            word = [];                               // 将单词置空
        } else if (s[left] !== ' ') {
            word.push(s[left]);                      // 将字符 push 进 word
        }
        left++;
    }
    // 记得要把最后一个单词拼接插入队列的头部
    // 因为最后一个单词后面没有空格:字符串末尾的空白字符已经在上一个 while 循环内被跳过
    queue.unshift(word.join(''));
    return queue.join(' ');
};

或者:
在这里插入图片描述

// javascript
var reverseWords = function(s) {
    const n = s.length;
    let left = 0, right = n - 1;
    while (left <= right && s[left] === ' ') {       // 去掉字符串开头的空白字符
        left++;
    }
    while (left <= right && s[right] === ' ') {      // 去掉字符串末尾的空白字符
        right--;
    }
    let i = right, j = right;
    const queue = [];
    while (i >= left) {
        while (i >= left && s[i] !== ' ') {          // 搜索前一个空格
            i--;
        }
        queue.push(s.slice(i + 1, j + 1));           // 添加单词
        while (i >= left && s[i] === ' ') {          // 跳过单词间空格
            //if (queue[queue.length - 1] !== ' ') {
            //    queue.push(' ');
            //}
            i--;
        }
        j = i;                                       // j 指向下个单词的尾字符
    }
    return queue.join(' ');                          // 拼接并返回,用空格拼接
    //return queue.join('');
};

在这里插入图片描述

解题三:原地翻转

因为部分语言(含 JS)字符串是不可改变的(immutable),所以 O ( 1 ) O(1) O(1) 额外空间复杂度的原地解法是不可能实现的。在这里用字符数组来模拟一下原地翻转的操作(除了 arr 字符数组外,空间复杂度为 O(1),如果字符串允许被改变,可以直接在 s 字符串上完成对 arr 字符数组的操作)。

// javascript
var reverseWords = function(s) {
    const n = s.length;
    const arr = s.split('');          // 转换成数组
    reverse(arr, 0, n - 1);           // 整个数组反转
    let start = 0;                    // start 记录处理后每个单词首字母的位置
    let fast = 0, slow = 0;           // 用快慢指针把 ' ' 移到非空格的后面(空格移到数组末尾)
    while (fast < n) {
        // fast 寻找下一个非空格元素
        if (arr[fast] !== ' ') {
            // 如果[0, fast]没有空格,slow、fast相等 -> 不交换,slow、fast移动后指向下一个需要判断的元素
            // 否则,将slow指向的空格和fast指向的非空格交换,[slow+1,fast-1]都是空格,slow指向下一个空格
            if (fast !== slow) {
                [arr[slow], arr[fast]] = [arr[fast], arr[slow]];
            }
            slow++;
            // 如果当前非空格元素的后一个元素是空格:说明 [start, slow - 1] 是一个单词(因为 slow++ 了)
            if (fast < n - 1 && arr[fast + 1] === ' ') {
                reverse(arr, start, slow - 1); // 单词反转
                slow++;                        // 单词之间需要空格,保留一个空格
                start = slow;                  // start 指向处理后下个单词首字母的位置
            }
        }
        fast++;
    }
    if (arr[slow - 1] === ' ') {               // 最后一个单词后面有多余空格导致它后面也保留了一个空格-删除
        slow--;
    } else {                                   // 否则最后一个单词后没有空格,在循环里未触发反转条件,要记得反转
        reverse(arr, start, slow - 1);
    }
    return arr.slice(0, slow).join('');        // [0, slow - 1] 是想要的部分,截取后拼接返回
};

const reverse = (arr, left, right) => {
    while (left < right) {
        [arr[left], arr[right]] = [arr[right], arr[left]];
        left++;
        right--;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值