class Solution:
def decodeAtIndex(self, s: str, k: int) -> str:
size = 0
# First, find the length of the decoded string
for c in s:
if c.isdigit():
size *= int(c)
else:
size += 1
for c in reversed(s):
k %= size
if k == 0 and c.isalpha():
return c
if c.isdigit():
size //= int(c)
else:
size -= 1
class Solution {
public:
string decodeAtIndex(string s, int k) {
long long size = 0;
for (char c : s) {
if (isdigit(c))
size *= c - '0';
else
size += 1;
}
for (int i = s.size() - 1; i >= 0; --i) {
k %= size;
if (k == 0 && isalpha(s[i]))
return string(1, s[i]);
if (isdigit(s[i]))
size /= s[i] - '0';
else
size -= 1;
}
return "";
}
};
class Solution {
public String decodeAtIndex(String s, int k) {
long size = 0;
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) {
size *= c - '0';
} else {
size++;
}
}
for (int i = s.length() - 1; i >= 0; --i) {
k %= size;
char c = s.charAt(i);
if (k == 0 && Character.isLetter(c)) {
return Character.toString(c);
}
if (Character.isDigit(c)) {
size /= c - '0';
} else {
size--;
}
}
return "";
}
}
var decodeAtIndex = function(s, k) {
let size = 0;
for (let c of s) {
if (/\d/.test(c)) {
size *= Number(c);
} else {
size += 1;
}
}
for (let i = s.length - 1; i >= 0; --i) {
k %= size;
if (k === 0 && /[a-zA-Z]/.test(s[i])) {
return s[i];
}
if (/\d/.test(s[i])) {
size = Math.floor(size / Number(s[i]));
} else {
size -= 1;
}
}
};
You are given a string s
that encodes letters and digits. The string is decoded by reading left to right: when you see a letter, it is written as-is; when you see a digit d
, the entire current decoded string is repeated d
times.
For example, s = "leet2code3"
decodes to "leetleetcodeleetleetcodeleetleetcode"
.
Given an integer k
, return the k-th letter in the decoded string. It is guaranteed that k
is valid (1-based index), and the decoded string is large enough.
At first, you might think to actually build the decoded string, then just return the k
-th character. However, with large input strings and digits, the decoded output can be huge (trillions of characters), making this approach impractical.
Instead, we need to find a way to determine the k
-th letter without building the whole string. The key is to simulate the decoding process in reverse, leveraging the way repetitions expand the string. By tracking the current length and working backwards, we can "skip" large blocks efficiently.
This shift from brute-force generation to mathematical reasoning is crucial for handling large inputs efficiently.
s
from left to right.size
counter.d
, multiply size
by d
.s
from right to left.k = k % size
. If k == 0
and the character is a letter, that's our answer.d
, divide size
by d
(undoing the previous multiplication).size
by 1.k
back through the repeated expansions to the original character.
We use this approach because it avoids actually constructing the massive decoded string, instead using math to trace k
to its source.
Let's use s = "leet2code3"
and k = 10
.
Final decoded length is 36.
When we reach 'o', k == 0
and it's a letter, so the answer is 'o'.
s
; decoded length can be huge.s
twice (forward and backward).This makes the optimized solution feasible even for very large decoded strings.
The main insight is that we don't need to actually decode the string to find the k
-th letter. By tracking the decoded string's length and reversing the decoding process, we can mathematically map k
back to its source character in s
. This approach is both elegant and efficient, handling even massive expansions with ease.