<p>The set <code>[1, 2, 3, ...,&nbsp;n]</code> contains a total of <code>n!</code> unique permutations.</p>

<p>By listing and labeling all of the permutations in order, we get the following sequence for <code>n = 3</code>:</p>

<ol>
	<li><code>&quot;123&quot;</code></li>
	<li><code>&quot;132&quot;</code></li>
	<li><code>&quot;213&quot;</code></li>
	<li><code>&quot;231&quot;</code></li>
	<li><code>&quot;312&quot;</code></li>
	<li><code>&quot;321&quot;</code></li>
</ol>

<p>Given <code>n</code> and <code>k</code>, return the <code>k<sup>th</sup></code> permutation sequence.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> n = 3, k = 3
<strong>Output:</strong> "213"
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> n = 4, k = 9
<strong>Output:</strong> "2314"
</pre><p><strong class="example">Example 3:</strong></p>
<pre><strong>Input:</strong> n = 3, k = 1
<strong>Output:</strong> "123"
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= n &lt;= 9</code></li>
	<li><code>1 &lt;= k &lt;= n!</code></li>
</ul>

from sortedcontainers import SortedList
class Solution:
    def getPermutation(self, n: int, k: int) -> str:
        fact = [0]*(n+1)
        fact[0] = 1
        for i in range(1, n+1):
            fact[i] = i * fact[i-1]
        
        sl = SortedList(list(range(1,n+1)))
        
        res = []
        # def find(pos):
        #     nonlocal k,fact
        #     curr = 0
        #     remain = n - pos - 1
        #     perm = fact[remain]
        #     for i in range(1,n+1):
        #         if seen[i]:
        #             continue
        #         new = curr+perm
        #         if curr <= k <= new:
        #             return (i, curr)
        #         curr += perm

        def find2(pos):
            nonlocal k,fact
            curr = 0
            remain = n - pos - 1
            perm = fact[remain]  # each number will contribute this
            # binary search 
            l = 0
            r = len(sl)-1
            while l <= r:
                mid = (l+r)//2
                cntl = (mid * perm)+1
                cntr = (mid+1) * perm
                if cntl <= k <= cntr:
                    return (sl[mid], cntl-1)
                elif cntl < k:
                    l = mid+1
                else:
                    r = mid-1
                    
            
        
        for i in range(n):
            num, sub = find2(i)
            sl.remove(num)
            k -= sub
            res.append(str(num))
        return "".join(res)
            
                
            
            
17200