1
+ //+ Jonas Raoni Soares Silva
2
+ //@ http://raoni.org
3
+
4
+ function reverseShuffleMerge ( s ) {
5
+ const required = new Map ( ) ;
6
+ const used = new Map ( ) ;
7
+ const available = new Map ( ) ;
8
+ for ( const c of s ) {
9
+ // As the string "S" is formed by the reverse of S + scrambled S, it means each character should appear twice...
10
+ // So we know which characters should be part of the original string and how many times they should appear
11
+ const amount = ( required . get ( c ) || 0 ) + .5 ;
12
+ // Keep the required amount (static reference) of characters to form the string
13
+ required . set ( c , amount ) ;
14
+ // As we collect chars, this will be used to monitor how many still exists ahead...
15
+ available . set ( c , amount * 2 ) ;
16
+ }
17
+ const origin = [ ] ;
18
+ // Reverse the string by making a loop from the end to the beginning
19
+ for ( let i = s . length ; i -- ; ) {
20
+ const c = s [ i ] ;
21
+ const count = used . get ( c ) || 0 ;
22
+ // If the current character is useful
23
+ if ( count < required . get ( c ) ) {
24
+ // Check if we can replace the last character we stored by a lexicographically smaller one...
25
+ for ( let last ; origin . length && ( last = origin [ origin . length - 1 ] ) > c ; origin . pop ( ) ) {
26
+ if ( used . get ( last ) + available . get ( last ) <= required . get ( last ) )
27
+ break ;
28
+ used . set ( last , used . get ( last ) - 1 ) ;
29
+ }
30
+ // Use character
31
+ used . set ( c , count + 1 ) ;
32
+ origin . push ( c ) ;
33
+ }
34
+ // Decrease the availability
35
+ available . set ( c , available . get ( c ) - 1 ) ;
36
+ }
37
+ return origin . join ( '' ) ;
38
+ }
0 commit comments