Kth Smallest Instructions

Bob is standing at cell (0, 0), and he wants to reach destination: (row, column). He can only travel right and down. You are going to help Bob by providing instructions for him to reach destination.

The instructions are represented as a string, where each character is either:

Multiple instructions will lead Bob to destination. For example, if destination is (2, 3), both "HHHVV" and "HVHVH" are valid instructions.


However, Bob is very picky. Bob has a lucky number k, and he wants the kth lexicographically smallest instructions that will lead him to destination. k is 1-indexed.

Given an integer array destination and an integer k, return the kth lexicographically smallest instructions that will take Bob to destination.

 

Example 1:

Input: destination = [2,3], k = 1
Output: "HHHVV"
Explanation: All the instructions that reach (2, 3) in lexicographic order are as follows:
["HHHVV", "HHVHV", "HHVVH", "HVHHV", "HVHVH", "HVVHH", "VHHHV", "VHHVH", "VHVHH", "VVHHH"].

Example 2:

Input: destination = [2,3], k = 2
Output: "HHVHV"

Example 3:

Input: destination = [2,3], k = 3
Output: "HHVVH"

 

Constraints:


Solution:

https://stackoverflow.com/questions/34230266/how-to-calculate-the-lexicographical-rank-of-a-given-permutation/34235272#34235272

class Solution {
    public String kthSmallestPath(int[] destination, int k) {
        int v = destination[0], h = destination[1];
        StringBuilder sb = new StringBuilder();
        long[][] combs = new long[31][31];
        for (int i = 0; i <= 30; i ++) {
            for (int j = 0; j <= i; j ++) {
                if (j == 0 || i == j) {
                    combs[i][j] = 1;
                } else {
                    // if A is picked, the rest possibilty is N-1 C j - 1
                    // if A is not picked, the rest is N - 1 C j
                    combs[i][j] = (combs[i - 1][j] + combs[i - 1][j - 1]);
                }
            }
        }
        nthP(sb, (long) k, h, v, combs);
        return sb.toString();
    }
    
    private void nthP(StringBuilder sb, long k, int h, int v, long[][] combs) {
        int t = h + v;
        for (int i = t; i > 0; i --) {
            if (i > v) {
                // assume we pick H, c is the max rank we can get
                // for example, for HHVVV, i = 5, c = 4C2 = 6
                // meaning if we pick H as first, there are ["HHHVV", "HHVHV", "HHVVH", "HVHHV", "HVHVH", "HVVHH"]
                // and if k is 7, then we have to pick V, and remove 6 from k
                long c = combs[i - 1][v];
                // we have to pick V
                if (k > c) {
                    k -= c;
                    sb.append('V');
                    v --;
                } else {
                    sb.append('H');
                }
            } else {
                sb.append('V');
            }
        }
    }
}