字母移位

96 阅读1分钟

这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情

问题描述

有一个由小写字母组成的字符串 s,和一个长度相同的整数数组 shifts。

我们将字母表中的下一个字母称为原字母的 移位 shift() (由于字母表是环绕的, 'z' 将会变成 'a')。

例如,shift('a') = 'b', shift('t') = 'u', 以及 shift('z') = 'a'。 对于每个 shifts[i] = x , 我们会将 s 中的前 i + 1 个字母移位 x 次。

返回 将所有这些移位都应用到 s 后最终得到的字符串 。

示例 1:

输入:s = "abc", shifts = [3,5,9]
输出:"rpl"
解释:
我们以 "abc" 开始。
将 S 中的第 1 个字母移位 3 次后,我们得到 "dbc"。
再将 S 中的前 2 个字母移位 5 次后,我们得到 "igc"。
最后将 S 中的这 3 个字母移位 9 次后,我们得到答案 "rpl"

示例 2:

输入: s = "aaa", shifts = [1,2,3]
输出: "gfd"

提示:

  • 1 <= s.length <= 10^5
  • s 由小写英文字母组成
  • shifts.length == s.length
  • 0 <= shifts[i] <= 10^9

思路分析

首先我们先要理解一下题目意思,题目会给我们一个字符串s和一个数组shifts,我们需要根据数组shifts对字符串s进行移位操作。这里需要注意的是:shifts[i]表示s的前i个字符都要移位shifts[i]次,也就是说第i个字符的移位次数应该是:∑(i,shifts.length-1)shifts[i],看到这里我们也就不难想出这道题目的解法了吧?

我们可以使用后缀和先求出每个字符需要移位的次数,再获取每个字符移位后的对应字符,即可得到移位后的字符串。

  • 后缀和计算各字符移位次数

从后往前遍历,第i位的值加上后一位的值即可。

for (let i = shifts.length - 2; i >= 0; i--) {
    shifts[i] = (shifts[i + 1] + shifts[i]) % 26;
}
  • 字符移位转换

我们可以使用charCodeAt方法获取字符的 Unicode 编码,再使用fromCharCode方法将 Unicode 编码转为一个字符。因为这里字母是首尾相连循环的,所以我们应该对移位操作次数进行对26取模。

let res = "";
for (let i = 0; i < shifts.length; i++) {
    let code = s[i].charCodeAt() - 97;
    code = ((code + shifts[i]) % 26) + 97;
    res += String.fromCharCode(code);
}

完整 AC 代码如下:

AC 代码

/**
 * @param {string} s
 * @param {number[]} shifts
 * @return {string}
 */
var shiftingLetters = function (s, shifts) {
  for (let i = shifts.length - 2; i >= 0; i--) {
    shifts[i] = (shifts[i + 1] + shifts[i]) % 26;
  }
  let res = "";
  for (let i = 0; i < shifts.length; i++) {
    let code = s[i].charCodeAt() - 97;
    code = ((code + shifts[i]) % 26) + 97;
    res += String.fromCharCode(code);
  }
  return res;
};

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。