Problem Statement in English
You’re given a string s consisting of lowercase English letters and the characters *, #, and %. You are also given an integer k. You need to return the k-th character of the string after processing it with the following operations:
- “*”: Delete the previous character.
- “#”: Append the current string to itself.
- “%”: Reverse the current string.
- Any other lowercase English letter: Append it to the current string.
Approach
The reason we can’t just simulate in this problem is because the string can get very large (upto $10^15$ according to the constraints), thus we need to find the k-th character without actually constructing the entire string.
Here’s the main problem – when the string is doubled, we have no way of knowing what the k-th character is without knowing the string before it was doubled.
So here’s how we counter that – we process the string in reverse.
This allows us to start with the length of the final string and work our way back to the original string, adjusting k as we go.
This means we need to use the complement of each operation as we iterate through it in reverse:
*:- Add 1 to the length of the string.
#:- Either
kis in the first half of the string, or it is in the second half. If it is in the second half, we subtract half the length of the string fromkand continue – this gives us the position of the character in the string before it was doubled. In either case we also halve the length of the string.
- Either
%:- We take the complement of
kwith respect to the length of the string, i.e.k = len - 1 - k. The reason we need to do this is because if we haven’t yet found thek-th character, it means that thek-th character is towards the end of the string we’re going toward, which means that the current reverse operation would have changed the position of thek-th character.
- We take the complement of
- Any other lowercase English letter: If the length of the string is equal to
k + 1, then we have found our character and we return it. Otherwise, we decrement the length of the string by 1.
And we’re done!
Solution in Python
class Solution:
def processStr(self, s: str, k: int) -> str:
n = len(s)
ln = 0
for c in s:
if c == '*':
ln = max(ln - 1, 0)
elif c == '#':
ln *= 2
elif c != '%':
ln += 1
if k >= ln:
return '.'
for i in reversed(range(n - 1)):
c = s[i]
if c == '*':
ln += 1
elif c == '#':
if k >= ln // 2:
k -= ln // 2
ln //= 2
elif c == '%':
k = ln - 1 - k
else:
if ln == k + 1:
return c
ln -= 1
Complexity
Time: $O(n)$
Since we are iterating through the stringstwice, the time complexity is linear with respect to the length of the string.Space: $O(1)$
Since we are not using any extra space, the space complexity is constant.
Mistakes I Made
I had to look this one up :(
And we are done.