LeetCode探索(155):557-反转字符串中的单词 III

99 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情

题目

给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:

输入:s = "Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"

示例 2:

输入: s = "God Ding"
输出:"doG gniD"

提示:

  • 1 <= s.length <= 5 * 10^4
  • s 包含可打印的 ASCII 字符。
  • s 不包含任何开头或结尾空格。
  • s至少 有一个词。
  • s 中的所有单词都用一个空格隔开。

思考

本题难度简单。

首先是读懂题意。 给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。可以注意到s 不包含任何开头或结尾空格,且s 中的所有单词都用一个空格隔开。

我们可以通过一行代码就解决该问题,也就是将句子拆分为单词,然后逐个单词翻转并连接起来。js 代码有时候显得很精炼!

我们也可以使用双指针的方法。定义 l 和 r 两个指针,表示单词的左右边界。遍历字符串 s,当碰到空格时,更新 r 为 i - 1,同时倒序遍历单词,最后添加当前空格,并更新 l 为 i + 1。当遍历到最后一个字符时,满足l < s.length,倒序添加该单词即可。

解答

方法一:一行代码解决

/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {
  return s.split(' ').map(str => [...str].reverse().join('')).join(' ')
}
// 执行用时:92 ms, 在所有 JavaScript 提交中击败了10.58%的用户
// 内存消耗:47.1 MB, 在所有 JavaScript 提交中击败了71.95%的用户
// 通过测试用例:29 / 29

复杂度分析:

  • 时间复杂度:O(n),其中 n 为字符串 s 的长度。
  • 空间复杂度:O(1)。

方法二:双指针

/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function(s) {
  let l = 0, r = 0, ans = ''
  for (let i = 0; i < s.length; i++) {
    if (s[i] === ' ') {
      r = i - 1
      let rr = r
      while (rr >= l) {
        ans += s[rr]
        rr--
      }
      ans += ' '
      l = i + 1
      // console.log(s.length, l, r)
    }
  }
  if (l < s.length) {
    rr = s.length - 1
    while (rr >= l) {
      ans += s[rr]
      rr--
    }
  }
  return ans
}
// 执行用时:80 ms, 在所有 JavaScript 提交中击败了34.94%的用户
// 内存消耗:47.1 MB, 在所有 JavaScript 提交中击败了64.18%的用户
// 通过测试用例:29 / 29

复杂度分析:

  • 时间复杂度:O(n),其中 n 为字符串 s 的长度。
  • 空间复杂度:O(1)。

参考