3307: Find-the-K-th-Character-in-String-Game-II
Hard
table of contents
The intuition is, to have constraints as large as
1 <= k <= 10^14
, there has to be some pattern that
exists allowing us to retrieve the k
th character
quickly.
You can see this come up in the example listed below, where you have input:
k
=10
operations
=[1, 0]
After 4 operations, we have this:
a|b|a|b|b|c|b|c|a|b| a| b| b| c| b| c
0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15
where the numbers below denote the letters respective index.
While looking at the letters and their respective
index, a pattern begins to reveal itself. Take index
11
as an example:
- index
11
came from index3
after operation0
a|b|a|*b*|b|c|b|c -> a|b| a|* b*| b| c| b| c
0|1|2|*3*|4|5|6|7 -> 8|9|10|*11*|12|13|14|15
- index
3
came from index1
after operation0
a|*b* -> a|*b*
0|*1* -> 2|*3*
- index
1
came from index0
after operation1
*a* -> *b*
*0* -> *1*
If we write 11
into binary, 0b1011
, and
relate the position of each 1
to an operation, for
example:
0b1011 & 0b0001 = 0b0001
so the11th
digit getsoperation[0 % 2] = 1
0b1011 & 0b0010 = 0b0010
so the11th
digit getsoperation[1 % 2] = 0
0b1011 & 0b0100 = 0b0100
so the11th
digit does not getoperation[2 % 2] = 1
0b1011 & 0b1000 = 0b1000
so the11th
digit getsoperation[3 % 2] = 0
which mirrors the operations and the order of the operations thekth
digit was placed through.
TLDR:
After n
operations, word
will be of length
2^n
. We know that the:
- first
2^(n-1)
characters was not affected by thenth
operation - last
2^(n-1)
characters was the result of thenth
operation on the first2^(n-1)
characters
Given their respective indices:
- the first
2^(n-1)
characters will have thenth
bit set to0
- the last
2^(n-1)
characters will have thenth
bit set to1
Using an inductive proof, we can show that the nth
bit
being set to 1
means that the respective operation has been
done on the kth
character.
code
class Solution {
public:
char kthCharacter(long long k, vector<int>& operations) {
char ans = 'a';
int index = 0;
-= 1;
k while (k > 0) {
if (k % 2 == 1 && operations[index] == 1) {
if (ans-'a' == 25) {
= 'a';
ans } else {
= ans+1;
ans }
}
= (index + 1) % operations.size();
index >>= 1;
k }
return ans;
}
};