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);
            }
        }
    }

方案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);
            }
        }
    }

测试:

输入
3
2 1
6 3
9 9
输出
3
42
1

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

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


总结

提示:重要经验:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰露可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值