<p>You are given a string <code>s</code> and a robot that currently holds an empty string <code>t</code>. Apply one of the following operations until <code>s</code> and <code>t</code> <strong>are both empty</strong>:</p>

<ul>
	<li>Remove the <strong>first</strong> character of a string <code>s</code> and give it to the robot. The robot will append this character to the string <code>t</code>.</li>
	<li>Remove the <strong>last</strong> character of a string <code>t</code> and give it to the robot. The robot will write this character on paper.</li>
</ul>

<p>Return <em>the lexicographically smallest string that can be written on the paper.</em></p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;zza&quot;
<strong>Output:</strong> &quot;azz&quot;
<strong>Explanation:</strong> Let p denote the written string.
Initially p=&quot;&quot;, s=&quot;zza&quot;, t=&quot;&quot;.
Perform first operation three times p=&quot;&quot;, s=&quot;&quot;, t=&quot;zza&quot;.
Perform second operation three times p=&quot;azz&quot;, s=&quot;&quot;, t=&quot;&quot;.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;bac&quot;
<strong>Output:</strong> &quot;abc&quot;
<strong>Explanation:</strong> Let p denote the written string.
Perform first operation twice p=&quot;&quot;, s=&quot;c&quot;, t=&quot;ba&quot;. 
Perform second operation twice p=&quot;ab&quot;, s=&quot;c&quot;, t=&quot;&quot;. 
Perform first operation p=&quot;ab&quot;, s=&quot;&quot;, t=&quot;c&quot;. 
Perform second operation p=&quot;abc&quot;, s=&quot;&quot;, t=&quot;&quot;.
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;bdda&quot;
<strong>Output:</strong> &quot;addb&quot;
<strong>Explanation:</strong> Let p denote the written string.
Initially p=&quot;&quot;, s=&quot;bdda&quot;, t=&quot;&quot;.
Perform first operation four times p=&quot;&quot;, s=&quot;&quot;, t=&quot;bdda&quot;.
Perform second operation four times p=&quot;addb&quot;, s=&quot;&quot;, t=&quot;&quot;.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= s.length &lt;= 10<sup>5</sup></code></li>
	<li><code>s</code> consists of only English lowercase letters.</li>
</ul>

from collections import deque


class Solution:
    def bad_sol_1(self, s: str) -> str:
        increasing = deque()

        for i in range(len(s)):
            while increasing and s[increasing[-1]] >= s[i]:
                increasing.pop()
            increasing.append(i)
        
        temp_letters = deque()
        ans = []
        current_index = 0

        while increasing:
            smallest_elem_index = increasing.popleft()
            
            for i in range(current_index, smallest_elem_index + 1):
                temp_letters.append(s[i])
            
            ans.append(temp_letters.pop())
            current_index = smallest_elem_index + 1
        
        while temp_letters:
            ans.append(temp_letters.pop())
            
        return "".join(ans)

    def tle_sol(self, s: str) -> str:
        t = deque()
        ans = []
        i = 0

        while i < len(s):
            # TODO: suboptimal
            s_smallest_elem = s[i]
            s_smallest_index = i
            for j in range(i+1, len(s)):
                if s[j] < s_smallest_elem:
                    s_smallest_elem = s[j]
                    s_smallest_index = j

            while t and t[-1] <= s_smallest_elem:
                ans.append(t.pop())
            
            for j in range(i, s_smallest_index+1):
                t.append(s[j])

            i = s_smallest_index + 1
        
        while t:
            ans.append(t.pop())

        return "".join(ans)

    def robotWithString(self, s: str) -> str:
        t = deque()
        ans = []
        i = 0

        # find smallest elements
        increasing_smallest_elems = deque()

        for i in range(len(s)):
            while increasing_smallest_elems and s[increasing_smallest_elems[-1]] > s[i]:
                increasing_smallest_elems.pop()
            increasing_smallest_elems.append(i)
        
        left = 0
        while increasing_smallest_elems:
            s_smallest_index = increasing_smallest_elems.popleft()

            while t and t[-1] <= s[s_smallest_index]:
                ans.append(t.pop())
            
            for j in range(left, s_smallest_index+1):
                t.append(s[j])
            
            left = s_smallest_index+1
        
        while t:
            ans.append(t.pop())

        return "".join(ans)

21600