848. Shifting Letters**
https://leetcode.com/problems/shifting-letters/
题目描述
We have a string S
of lowercase letters, and an integer array shifts
.
Call the shift of a letter, the next letter in the alphabet, (wrapping around so that 'z'
becomes 'a'
).
For example, shift('a') = 'b'
, shift('t') = 'u'
, and shift('z') = 'a'
.
Now for each shifts[i] = x
, we want to shift the first i+1
letters of S
, x
times.
Return the final string after all such shifts to S
are applied.
Example 1:
Input: S = "abc", shifts = [3,5,9]
Output: "rpl"
Explanation:
We start with "abc".
After shifting the first 1 letters of S by 3, we have "dbc".
After shifting the first 2 letters of S by 5, we have "igc".
After shifting the first 3 letters of S by 9, we have "rpl", the answer.
Note:
1 <= S.length = shifts.length <= 20000
0 <= shifts[i] <= 10 ^ 9
C++ 实现 1
这题本身并不难, 关键在于要防止 overflow. 拿例子来说, 对于 c
, 需要移动 9 次, 而对 b
来说, 需要移动 9 + 5 = 14
次, 而 a
需要移动 9 + 5 + 3 = 17
次. 对 26
(26 个小写字母) 求余. 但这是 shifts
中的值较小的情况. 如果 shifts
中的值很大, 从后向前累加, 可能会造成整数 overflow. 这时, 需要提前求余:
class Solution {
private:
char shift(const char &c, int n) {
char res = (c - 'a' + n) % 26 + 'a';
return res;
}
public:
string shiftingLetters(string S, vector<int>& shifts) {
// 累加和的时候就应该求余
for (int i = shifts.size() - 2; i >= 0; -- i)
shifts[i] = (shifts[i + 1] + shifts[i]) % 26;
for (int i = 0; i < S.size(); ++ i)
S[i] = shift(S[i], shifts[i]);
return S;
}
};
原理在于公式: 可以参看 974. Subarray Sums Divisible by K**
(a + b) mod n = [(a mod n) + (b mod n)] mod n
(a mod n) mod n = a mod n
看 n - 3
这个位置的公式推导:
C++ 实现 2
也可以写成如下的形式:
class Solution {
private:
char shift(const char &c, int n) {
char res = (c - 'a' + n) % 26 + 'a';
return res;
}
public:
string shiftingLetters(string S, vector<int>& shifts) {
int prev = 0;
for (int i = S.size() - 1; i >= 0; -- i) {
prev = (prev + shifts[i] % 26) % 26;
// 注意和 C++ 实现 1 不同的是, 这里的第二个参数是 prev
S[i] = shift(S[i], prev);
}
return S;
}
};