【算法-LeetCode】151. 翻转字符串里的单词(双指针/滑动窗口;字符串;正则;数组方法)

151. 翻转字符串里的单词 - 力扣(LeetCode)

发布:2021年9月22日23:30:09

问题描述及示例

给你一个字符串 s ,逐个翻转字符串中的所有 单词 。

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

请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。

说明:

  • 输入字符串 s 可以在前面、后面或者单词间包含多余的空格。
  • 翻转后单词间应当仅用一个空格分隔。
  • 翻转后的字符串中不应包含额外的空格。

示例 1:
输入:s = “the sky is blue”
输出:“blue is sky the”

示例 2:
输入:s = " hello world "
输出:“world hello”
解释:输入字符串可以在前面或者后面包含多余的空格,但是翻转后的字符不能包括。

示例 3:
输入:s = “a good example”
输出:“example good a”
解释:如果两个单词间有多余的空格,将翻转后单词间的空格减少到只含一个。

示例 4:
输入:s = " Bob Loves Alice "
输出:“Alice Loves Bob”

示例 5:
输入:s = “Alice does not even like bob”
输出:“bob like even not does Alice”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-words-in-a-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

提示:
1 <= s.length <= 104
s 包含英文大小写字母、数字和空格 ’ ’
s 中 至少存在一个 单词

我的题解

我的题解1(利用JavaScript原生API)

总体思路非常简单:

  1. 先利用 trim() 函数把 s 头尾的空格给删掉;
  2. 再利用 replace() 函数和正则表达式把 s 中的一个或多个空格字符统一替换成一个空格;
  3. 再利用 split() 函数把 s 字符串以空格为分隔符分割为若干部分,每一部分就是一个单词;
  4. 然后利用 reverse() 函数将拆分后的单词倒置;
  5. 最后利用 join() 函数把倒置后的各个单词以空格为分隔符重新拼接成一个符合要求的字符串。
/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {
  s = s.trim();
  s = s.replace(/\s+/g,' ');
  return s.split(' ').reverse().join(' ');
};


提交记录
57 / 57 个通过测试用例
状态:通过
执行用时:72 ms, 在所有 JavaScript 提交中击败了75.00%的用户
内存消耗:39.1 MB, 在所有 JavaScript 提交中击败了84.29%的用户
时间:2021/09/22 23:43

当然这种做法有点作弊的嫌疑。还是不大推荐的。

我的题解2(双指针/滑动窗口)

更新:2021年9月23日20:21:28

主要思路是用两个指针来确定一个单词的边界。front 指针用于确定单词的前边界,而 back 指针则用于确定单词后边界。

逐位遍历 s 中的每个字符,如果发现当前某个字符为空格,而该字符紧接着的下一个字符不是空格,那就说明找到了一个单词的前边界了,于是让 front 指针指向相应位置;

继续往后遍历,如果发现当前的某个字符不为空格,而该字符紧接着的下一个字符是空格,那就说明找到了一个单词的后边界了,于是让 back 指针指向相应位置。

这时程序也就已经找到了一个完整的单词,所以此时也要根据找到的这两个单词边界来将找到的这个单词压入 words 数组中。

words 在这里充当了一个栈结构,只不过这里是把数组尾部当做栈的底部,数组头部当做栈顶。

当所有字符都遍历完了,那句子中的额所有单词也就都被找到并按被找到的顺序的倒序存储在了 words 中,最后只要将 words 中的元素用空格拼接为字符串即为我们想要的结果。

这道题的难点在于某些边界条件的判断,比如:s 的开头或结尾不是空格。那就要花好些功夫做额外的判断了,而且针对开头非空格的情况又有特殊情况,即:开头的单词是单个字符,比如 'a good example',那又得额外考虑了……为了不对那么多特殊情况另外做判断,我给每个传入的 s 的头尾都特意增加了一个空格,这样就能适应所有的用例而不用针对某些用例做特殊判断了。

/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {
  // 特意给 s 的头尾各自额外增加一个空格来应对某些特殊的用例
  s = ' ' + s + ' ';
  // front指针用于确定一个单词的前边界
  let front = 0;
  // 一开始我特意声明了一个back变量来表示后指针的,但是后来发现直接用for循环中的i是等效的
  // let back = 0;
  // words用于存储找到的各个单词,是一个栈结构
  let words = [];
  // 开始逐位遍历s中的字符,back指针用于确定一个单词的后边界
  for(let back = 0; back < s.length; back++) {
    // 如果当前字符为空格且下一个字符不为空格,则说明当前字符的下一个字符就是一个单词首字母
    // 这里要注意空字符和空格字符的区别,空格转化为布尔值为true,而空字符则为false
    if(s[back] === ' ' && s[back+1] !== ' ') {
      front = back+1;
    }
    // 如果当前字符不为空格且下一个字符为空格,则说明当前字符即为一个单词的最后一个字母
    if(s[back] !== ' ' && s[back+1] === ' ') {
      // back = i;
      // 此时就已将找到了一个完整的单词,根据找到的边界将其压入words栈
      words.unshift(s.substring(front, back+1));
    }
  }
  // 遍历完 s 中所有字符后,也就找到了所有完整的单词,将这些单词以空格拼接起来即可
  return words.join(' ');
};


提交记录
57 / 57 个通过测试用例
状态:通过
执行用时:76 ms, 在所有 JavaScript 提交中击败了56.79%的用户
内存消耗:39.7 MB, 在所有 JavaScript 提交中击败了30.72%的用户
时间:2021/09/23 20:12	

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

【更新结束】

更新:2021年9月22日21:59:50

参考:翻转字符串里的单词 - 翻转字符串里的单词 - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年9月22日23:36:15
参考:String.prototype.trim() - JavaScript | MDN
参考:String.prototype.replace() - JavaScript | MDN
参考:javascript将字符串中的多个空格替换为一个空格的正则实例 - 走-走 - 博客园
更新:2021年9月23日20:20:20
参考:Array.prototype.unshift() - JavaScript | MDN

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值