开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第24天,点击查看活动详情
问题描述
给你一个小写英文字母组成的字符串 s 和一个二维整数数组 shifts ,其中 shifts[i] = [starti, endi, directioni] 。对于每个 i ,将 s 中从下标 starti 到下标 endi (两者都包含)所有字符都进行移位运算,如果 directioni = 1 将字符向后移位,如果 directioni = 0 将字符向前移位。
将一个字符 向后 移位的意思是将这个字符用字母表中 下一个 字母替换(字母表视为环绕的,所以 'z' 变成 'a')。类似的,将一个字符 向前 移位的意思是将这个字符用字母表中 前一个 字母替换(字母表是环绕的,所以 'a' 变成 'z' )。
请你返回对 s 进行所有移位操作以后得到的最终字符串。
示例 1:
输入: s = "abc", shifts = [[0,1,0],[1,2,1],[0,2,1]]
输出: "ace"
解释: 首先,将下标从 0 到 1 的字母向前移位,得到 s = "zac" 。
然后,将下标从 1 到 2 的字母向后移位,得到 s = "zbd" 。
最后,将下标从 0 到 2 的字符向后移位,得到 s = "ace" 。
示例 2:
输入: s = "dztz", shifts = [[0,0,0],[1,1,1]]
输出: "catz"
解释: 首先,将下标从 0 到 0 的字母向前移位,得到 s = "cztz" 。
最后,将下标从 1 到 1 的字符向后移位,得到 s = "catz" 。
提示:
1 <= s.length, shifts.length <= 5 * 104shifts[i].length == 30 <= starti <= endi < s.length0 <= directioni <= 1s只包含小写英文字母。
思路分析
首先我们要先理解一下题意,题目会给我们一个字符串 s 和一个二维整数数组 shifts,其中 shifts[i] = [starti, endi, directioni] 。对于每个 i ,将 s 中从下标 starti 到下标 endi (两者都包含)所有字符都进行移位运算,如果 directioni = 1 将字符向后移位,如果 directioni = 0 将字符向前移位。也就是说我们要根据shifts数组的描述对s字符串进行移位操作,操作方式只有两种:
- 1、向前移位,如
a->z、z->a - 2、向后移位,如
a->b,z->a
每次操作我们需要对s 中从下标 starti 到下标 endi区间中的所有字符进行移位,这是一个很明显的区间操作,我们可以使用差分数组来进行解题。如果需要对LR范围内所有数都进行相同的操作,我们不需要从LR遍历arr然后在每个值上进行相同操作,只需要在差分数组d中改变L和R+1的值即可,最后再进行一次前缀和计算便可以将修改后的数组还原出来。
- 1、构建差分数组
如果需要对LR范围内所有数都进行相同的操作,我们不需要从LR遍历arr然后在每个值上进行相同操作,只需要在差分数组d中改变L和R+1的值即可。
let res = new Array(s.length + 1).fill(0);
for(let i = 0; i < shifts.length; i++){
res[shifts[i][0]] += (shifts[i][2] == 0 ? -1 : 1);
res[shifts[i][1] + 1] -= (shifts[i][2] == 0 ? -1 : 1);
}
- 2、前缀和还原
使用前缀和计算可以将所有位置的操作数计算出来。
for(let i = 0; i < s.length; i++){
res[i] += (res[i - 1] || 0);
}
- 3、计算操作后的字符
得到了每个字符的操作记录之后,我们就可以对每个字符进行对应的移位操作得到移位后的新字符。
let ans = '';
for(let i = 0; i < s.length; i++){
res[i] += (res[i - 1] || 0);
while(res[i] < 0) res[i] += 26;
res[i] %= 26;
let code = s[i].charCodeAt() + res[i];
if(code > 122) code = code % 123 + 97;
ans += String.fromCharCode(code);
}
AC代码
完整代码如下:
/**
* @param {string} s
* @param {number[][]} shifts
* @return {string}
*/
var shiftingLetters = function(s, shifts) {
let res = new Array(s.length + 1).fill(0);
for(let i = 0; i < shifts.length; i++){
res[shifts[i][0]] += (shifts[i][2] == 0 ? -1 : 1);
res[shifts[i][1] + 1] -= (shifts[i][2] == 0 ? -1 : 1);
}
let ans = '';
for(let i = 0; i < s.length; i++){
res[i] += (res[i - 1] || 0);
while(res[i] < 0) res[i] += 26;
res[i] %= 26;
let code = s[i].charCodeAt() + res[i];
if(code > 122) code = code % 123 + 97;
ans += String.fromCharCode(code);
}
return ans;
};
说在后面
本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。