JS算法之和为s的连续正数序列及翻转单词顺序

214 阅读3分钟

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

和为s的连续正数序列

剑指Offer 57 - II. 和为s的连续正数序列

难度:简单

题目:leetcode-cn.com/problems/he…

输入一个正整数target,输出所有和为target的连续正整数系列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

示例1:

输入:target = 9
输出:[[2,3,4],[4,5]]

示例2:

输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

限制:1 <= target <= 10^5

题解

滑动窗口

通过示例可以看出,数组最后一个数字,如果target是偶数则就是为target/2,如果是奇数则就是target/2取整加一。

/**
 * @param {number} target
 * @return {number[][]}
 */
var findContinuousSequence = function (target) {
  let index = Math.ceil(target / 2);
  // res为结果,temp为结果中的每一个数组,sum用于判断是否等于target
  let res = [],
    temp = [],
    sum = 0;
  for (let i = 1; i <= index; i++) {
    temp.push(i);
    sum += i;
    // 如果sum > target,将temp头部推出,滑动窗口
    while (sum > target) {
      sum -= temp[0];
      temp.shift();
    }
    // 如果在循环过程中,sum等于target,将temp放入res
    if (sum === target) {
      temp.length >= 2 && res.push([...temp]);
    }
  }
  return res;
};

或

// 双指针
var findContinuousSequence = function (target) {
  let l = 1,
    r = 2,
    sum = 3;
  let res = [];
  while (l < r) {
    if (sum === target) {
      let ans = [];
      for (let k = l; k <= r; k++) {
        ans[k - l] = k;
      }
      res.push(ans);
      // 若等于,可以让窗口继续右移,同时缩小左边的
      sum = sum - l;
      l++;
    } else if (sum > target) {
      // 若大于,缩小窗口
      sum = sum - l;
      l++;
    } else {
      // 若小于,扩大窗口
      r++;
      sum = sum + r;
    }
  }
  return res;
};
  • 时间复杂度:O(NN)
  • 空间复杂度:O(11)

翻转单词顺序

剑指Offer 58 - I. 翻转单词顺序

难度:简单

题目:leetcode-cn.com/problems/fa…

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串“I am a student.”,则输出 “student. a am I”。

示例1:

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

示例2:

输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例3:

输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

说明:

  • 无空格字符构成一个单词。
  • 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
  • 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

题解

法一 使用API

  • trim()删除字符串两端空格
  • split(' ')切割空格变为数组
  • filter()过滤数组中的空格
  • reverse()反转数组
  • join(' ')以空格为界限,数组转字符串
/**
 * @param {string} s
 * @return {string}
 */
var reverseWords = function (s) {
  let str = s.trim().split(' ').filter(item => item != '').reverse().join(' ');
  return str;
};
  • 时间复杂度:O(NN)
  • 空间复杂度:O(NN)

法二 双指针

步骤:

  • 去掉首尾空格,从后往前遍历字符串s,记录左右索引边界i和j
  • 每确定一个单词的边界,则将单词放入数组res
  • 数组res转字符串后返回
var reverseWords = function (s) {
  // 1.去掉首尾空格 
  s = s.trim();

  let j = s.length - 1,
    i = j;
  let res = [];

  while (j >= 0) {
    while (i >= 0 && s[i] !== ' ') i--;// 搜索空格
    res.push(s.slice(i + 1, j + 1)); // 添加单词
    while (j >= 0 && s[i] === ' ') i--; // 跳过空格
    j = i; // j指向下一个单词
  }
  return res.join(' '); // 数组转字符串
};
  • 时间复杂度:O(NN)
  • 空间复杂度:O(NN)

坚持每日一练!前端小萌新一枚,希望能点个哇~