爬楼梯问题, 求有多少种走法。 性能二次改良- 算法与数据结构面试分享(二十二)

题目:我们在上楼梯的时候,假设我们一次上一个台阶,也可以上两个台阶,如果现在有N个台阶,请问它有多少种走法?能帮我实现一个算法吗?

很多同学拿到这道题的时候,想到的是数学问题。不过很多人不小心就陷入了排列组合,在N中求出1与2的组合可能有多少?按照这种思路估计就解不出来这道题了。要理解这道题得从下面两个方面入手:

  1.  什么叫走法?假设我们现在有3个台阶,它的走法有(1,1,1),(1,2),(2,1),一共三种走法,其实就是X个1和Y个2加起来是N,我们现在去求X个1与Y个2的排列。这里的第一种走法就是每次迈一个台阶对吧?
  2. 我们走走看,从第一步开始,回顾整个过程。假设有N个台阶,第一步有两种选择,我们假设无论哪种选择,之后都还有台阶

  • 第一次上一个,还剩下 N-1个,这时候有多少种走法取决于 N-1个台阶有多少种走法,每种走法的第一步都是1,已经确定了
  • 第一次上二个,还剩N-2个,这时候还有多少种走法取决于N-2个台阶有多少种走法,每种走法的第一步都是2,已经确定了

这个时候,大家是不是似乎明白了什么?是不是 当N > 2 时,F(N) = F(N-1) + F(N-2), 而 F(1) = 1, F(2) = 2?

答案就是这么简单,它的递归式就是斐波那契数列对吧。 好的,那我们的编程就很容易实现了。直接上代码哈。

     public static int F(int n)
        {
            if (n > 0 && n <3) return n;

            return F(n - 1) + F(n - 2);
        }

大家可以自己试一下,按照这种方法求出 F(100)看看要多久?很久很久的!!!! 

我们现在对这个算法做一些改良

  • 第一步改良, F(n) = F(n-1) + F(n-2), F(n-1) = F(n-2) + F(n-3), 这时候我们发现 F(n-2)算了两次,我们我们需要把它保存下来,减少重复计算。不过这个其实还是递归!
        public static int F1(int n)
        {
            int[] array = new int[n + 1];
            if (n < 3 && n > 0) return n;
            array[1] = 1;
            array[2] = 2;
            return FHelper(array, n);
        }

        private static int FHelper(int[] array, int n)
        {
            if (n > 0 && n < 3)
            {
                return n;
            }
            array[n] = FHelper(array, n - 1) + array[n - 2]; 
            return array[n];
        }

  • 第二步改良,这样的递归其实可以采取递推的方式来计算的,后面我也打算和大家分享动态规划的内容,到时候可能还会和大家讲这道题。我们可以从1-N的方向解题,每次保存2个数, F(1), F(2),  我们就能求出F(3)了。我们再一起看代码
        public static int F2(int n)
        {
            if (n > 0 && n < 3)
                return n;

            else if (n >= 3)
            {
                int first = 1, second = 2;
                int third = 0;
                for (int i = 3; i <= n; i++)
                {
                    third = first + second;
                    first = second;
                    second = third;
                }

                return third;
            }

            throw new ArgumentException("N 应该大于0");
        }

第二种改良方法中已经没有递归了,不过它有更加容易理解的方式去写。之后我会给大家介绍这种递归改良的套路。

还没有结束哈。大家再想一想,如果这种人足够强壮,他每次抬脚,可以走一步,两步,或者三步,那大家能自己写出来一共有多少种走法呢?

好了,我们这道题就先聊到这哈。感兴趣的同学可以加我们的QQ群参与讨论,微信公众号获取更多资讯。还欢迎大家访问我的视频教程,了解更多经典面试题。

算法与数据结构

经典面试题

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值