给定一个编码字符串 S。请你找出 **解码字符串 并将其写入磁带。解码时,从编码字符串中 每次读取一个字符 ,并采取以下步骤:
- 如果所读的字符是字母,则将该字母写在磁带上。
- 如果所读的字符是数字(例如
d),则整个当前磁带总共会被重复写d-1次。
现在,对于给定的编码字符串 S 和索引 K,查找并返回解码字符串中的第 K 个字母。
示例 1:
输入: S = "leet2code3", K = 10
输出: "o"
解释:解码后的字符串为 "leetleetcodeleetleetcodeleetleetcode"。字符串中的第 10 个字母是 "o"。
示例 2:
输入: S = "ha22", K = 5
输出: "h"
解释:解码后的字符串为 "hahahaha"。第 5 个字母是 "h"。
示例 3:
输入: S = "a2345678999999999999999", K = 1
输出: "a"
解释: 解码后的字符串为 "a" 重复 8301530446056247680 次。第 1 个字母是 "a"。
题解
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
// 逆向模拟,由于题目规模较大,要用 BigInt
// 举例:S = "leet2code3", K = 10
// 1. 正向求出 S 的总长度 size = 36
// 2. 逆向遍历 S,区分遇到数字和字母的情况
// 遇到 3, k = 10 % 36 = 10, size = 36 / 3 = 12;
// 遇到 e, k = 10 % 12 = 10, size--, size = 11
// 遇到 d, k = 10 % 11 = 10, size--, size = 10
// 遇到 o, k = 10 % 10 = 0, k === 0, 返回 'o'
var decodeAtIndex = function (s, k) {
let len = s.length;
let size = 0n;
k = BigInt(k);
// 计算出字符串长度 遇到字符时 size ++ 遇到数字 size * v
for (let i = 0; i < len; i++) {
const v = s[i];
if (isNum(v)) {
size *= BigInt(v);
} else {
size++;
}
}
// 逆向遍历字符S
for (let i = len - 1; i >= -1; i--) {
k = k % size;
const v = s[i];
if (isCh(v) && k === 0n) {
return v;
}
// size 值区分当前值时字符还是数字
if (isNum(v)) {
size /= BigInt(v);
} else {
size--;
}
}
};
function isCh(x) {
return /[a-z]/.test(x);
}
function isNum(x) {
return /[2-9]/.test(x);
}
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。