算法

1643-第 K 条最小指令-经典第k问题

2020-11-01  本文已影响0人  华雨欣

写在前面

这周周赛的最后一道题,其实难度不是很大,而且第K问题是很经典的,还是我做过的问题,但是当时脑子就是转不过来个,怎么都想不出来,只想到了暴力枚举,TLE收了尾。。。

题目


比赛里看了题目数据范围最大只有15,一个激动直接O(2^N)暴力搜索,结果要行列同时考虑,相当于数据范围在30左右,直接就超时了。

核心思路

由于起点终点确定,代表了我们向右移动的步数和向下移动的步数都已经固定为hv,那么题目求解的就是在 h个H和v个V的组合中第K小的字符串
如果我们考虑当前位置 i (i之前已经确定)应该是什么字符,由于H小于V,所以可以想到所有当前位置是H的字符串都小于当前位置是V的字符串,那么如果我们知道当前位置是H的字符串的数量,再与目标k进行比较,就可以明确的确定当前位置到底是H 还是 V 了。
那么这个数该怎么求呢?根据排列组合思想,如果当前位置还不放字符时HV的数量分别为 h 和 v ,那么当前位置取H对应的组合数就是nCr(h - 1 + v, h - 1),所以我们不妨提前算出题目范围的所有组合数,然后根据上边的思路逐个位置确定该放什么字符即可。

完整代码

class Solution {

    int[][] C;

    public String kthSmallestPath(int[] destination, int k) {
        int h = destination[1];
        int v = destination[0];
        C = new int[h + v + 1][h + v + 1];
        C[0][0] = 1;
        for(int i = 1; i <= h + v; i++){
            C[i][0] = 1;
            for(int j = 1; j <= i; j++)
                C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
        }

        String res = "";
        int all = h + v;
        for(int i = 0; i < all; i++){
            if(h > 0){
                int num = C[h + v - 1][h - 1];
                if(k > num){
                    res += 'V';
                    v--;
                    k -= num;
                }else{
                    res += 'H';
                    h--;
                }
            }else{
                res += 'V';
                v--;
            }
        }
        return res;
    }
}

因为数据范围比较小,直接使用杨辉三角递推求组合数即可。对于求出的组合数,如果k比较大的话,说明第k条指令的当前位置应该以V开头,反之应该以H开头。
这道题真的越看越觉得眼熟,但是就是想不起来是哪道题、怎么做了,自己思路还是不够开拓啊,一点点继续努力加油了。如果文章有写的不正确的地方还请指出,感恩相遇~~

上一篇 下一篇

猜你喜欢

热点阅读