题目地址:
https://leetcode.com/problems/decoded-string-at-index/description/
给定一个长 n n n的编码过的字符串 s s s,其只含英文小写字母和 2 ∼ 9 2\sim 9 2∼9的数字,其还原方式如下:读到字符则记录,读到数字 c c c则将记录好的字符串重复 c c c遍。问还原后的字符串的第 k k k个字符是什么。题目保证 s s s以字母开头,且 k k k一定有效。计数从 1 1 1开始。
先求还原后的总长度 m m m,然后我们一步步“加密”回来寻找答案,加密的过程即为从后向前遍历 s s s的过程,也是递归的思想。从后向前遍历 s s s,如果遇到数字 c c c,则说明加密一次后字符串变为了 m / c m/c m/c,并且第 k k k个字符即为加密后的第 k m o d ( m / c ) k\mod (m/c) kmod(m/c)个字符(如果余数是 0 0 0则说明是最后一个字符),所以我们考虑加密 1 1 1次后的新字符串,其长度即为 m / c m/c m/c,我们要求新字符串的第 k m o d ( m / c ) k\mod (m/c) kmod(m/c)个字符(余数是 0 0 0则是最后一个字符);如果遇到的是字符,此时如果 m = k m=k m=k,则当前字符就是我们要找的字符,否则我们考虑少了最后那个字符的新字符串,其长度为 m − 1 m-1 m−1,我们还是要找第 k k k个字符。无论怎样,问题的规模都会缩小。代码如下:
class Solution {
public:
string decodeAtIndex(string s, int k) {
long n = 0;
for (char ch : s)
if (isdigit(ch)) n *= ch - '0';
else n++;
for (int i = s.size() - 1; i >= 0; i--) {
char ch = s[i];
if (isdigit(ch)) {
int x = ch - '0';
// 我们要在新的长n/x的串里找第k%n个字符
n /= x;
k %= n;
if (!k) k = n;
} else {
if (n == k) return string(1, ch);
n--;
}
}
return "";
}
};
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。