• LeetCode高频题:戈壁滩种树,一排n棵树,至少有k棵树存活时,最终形成的风景线有多少不同的情况


    LeetCode高频题:戈壁滩种树,一排n棵树,至少有k棵树存活时,最终形成的风景线有多少不同的情况

    提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
    互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
    你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题
    在这里插入图片描述


    题目

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    一、审题

    示例:看上面


    二、解题

    这题,挺恶心的,当时看我朋友测试案例就只能过50%

    很巧……我怀疑后台测试案例有问题

    否则怎么巧了1/2概率对呢

    方案1,就是算排列组合

    在这里插入图片描述
    n个树,任选k个树活着
    因为是至少k个,所以可能k+1个活着呢
    k+2活着呢
    又或者就是n个全活了

    所以就是连加

    结果它代码50%过,不懂为啥????

    手撕代码

        public static class Main2{
            //gcd(a,b)的公式,我们早讲过无数次,死记硬背:b=0,返回a,否辗转相处求gcd(b,a%b)
            public static long gcd(long a, long b){
                return b == 0 ? a : gcd(b, a % b);
            }
            //正式用gcd来月C(n,k)的分子分母,防止溢出,计算C(n,k)
            public static int Cnk(int n, int k){
                long a = 1;//分母
                long b = 1;//分子//上面说了哦,分母a从n-k+1开始到n连成阶乘//分子b从1--k连成阶乘//a/b在循环时将gcd约了//i帮着分母循环,j帮着分子循环
                for (int i = n - k + 1, j = 1; i <= n || j <= k; i++, j++) {
                    //当i或者j越界了也没事,因为ab,最终会约的
                    a *= i;
                    b *= j;//分母分子轮番乘自己的阶乘//然后约
                    long gcd = gcd(a, b);
                    a /= gcd;
                    b /= gcd;
                }
                return (int) (a / b);
            }
            public static void main(String[] args) {
                Scanner in = new Scanner(System.in);
                int t = in.nextInt();
                for (int i = 0; i < t; i++) {
                    int n = in.nextInt();
                    int k = in.nextInt();
                    int ans = 0;
                    for (int j = k; j <= n; j++) {
                        ans += Cnk(n, j);
                    }
                    System.out.println(ans);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    方案2,动态规划:定义dp一个二维表格,dpij代表啥呢?从0–i个树中任选j个树活着,情况有多少种?

    dp是n+1乘n+1的格子
    i行代表0–i个树里面随意挑树
    挑j个活着(必须活着)

    (0)dp[0][0]=1,为啥,从0个树里面选j=0个树活着,就是不选,方法为1种
    (1)0行,全是0,为啥呢,没有树,你不可能选j个活着啊
    (2)0列,全是1,为啥呢,有树,但是只能选j=0个活着,就是不选,方案1种
    在这里插入图片描述
    (4)剩下的dpij任意格子怎么求?
    很简单,只看i位置的树活着,还是死了?
    i活着的话,那从0–i-1范围上只需要选j-1根树活着(拢共就j个活着呗)
    i死了的话,那从0–i-1范围上必须得选j根树活着(拢共就j个活着呗)

    这两种情况加起来就是dpij

    手撕代码:

    public static class Main{
            public static void main(String[] args) {
                Scanner in = new Scanner(System.in);
                int mod = (int) (1e9+7);
                int t = in.nextInt();
                for (int x = 0; x < t; x++) {//t次
                    int n = in.nextInt();
                    int k = in.nextInt();
                    int[][] dp = new int[n + 1][n + 1];//从0--i行选j个树活着
                    dp[0][0] = 1;//0棵树范围上选0活着,方法就一种,不选
                    //0行,其他默认0,只有0棵树,就不可能有j=1以上的树活着
                    for (int i = 1; i <= n; i++) {//现在只填0列
                        dp[i][0] = 1;//树必死
                    }
                    for (int i = 1; i <= n; i++) {
                        for (int j = 1; j <= n; j++) {
                            dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] % mod;//i活着,i死了两种情况
                        }
                    }
    
                    int ans = 0;
                    for (int j = k; j <= n; j++) {
                        ans += dp[n][j];
                    }
                    System.out.println(ans);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    测试:

    输入
    3
    2 1
    6 3
    9 9
    输出
    3
    42
    1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    很OK,就是不知道蔚来后台到底是怎么了,尴尬,只过了50%

    2种方案都是,没道理啊,蔚来一直很坑,非常不爽


    总结

    提示:重要经验:

    1)动态规划,nk显然就是样本位置对应模型,整一个二维表即可,摸索很快就OK了
    3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

  • 相关阅读:
    iOS打包 rebuild from bitcode对ipa大小的影响
    刷题学习记录
    考研:研究生考试(五天学完)之《线性代数与空间解析几何》研究生学霸重点知识点总结之第五课线性方程组
    Java Coding Problems Second Edition --chapter 01
    (数据科学学习手札134)pyjanitor:为pandas补充更多功能
    Linux 终端 Ctrl + C 无法终止当前程序(详细解决步骤)
    Godot 4.0 加载为占位符(InstancePlaceholder)的用法和特点
    闲来无事-树莓派控制风扇启停
    SpringBoot 使用过滤器修改请求参数
    Gin+WebSocket实战——在线聊天室WebSocketDemo详细使用教程
  • 原文地址:https://blog.csdn.net/weixin_46838716/article/details/126670893