腾讯面试题:50个阶梯,你一次可以上一阶或两阶,走上去,共有多少种走法【原】

有个同学去了腾讯,他说面试时有这么一道思维题:50个阶梯,你一次可以上一阶或两阶,走上去,共有多少种走法?

我的思路: 

我的思维比较直线简单:

1,求出走上去可能有的方式,这里的方式是指:共走多少个1步,多少个2步。比如说,你走了2个1步,其余走2步,要走24个2步,用对象存起来就是:{one:2,two:24}

2,每个方式的走法是可以通过排列组合公式算出来的。如下是排列组合公式:

     

 3,用到的公式是c(n,r)=n!/r!(n-r)!;这个比较好实现,无非就是阶乘除阶乘。

代码如下:

        (function() {
            var waysArr = []; //上台阶方式的,每一种方式为一个对象字面量,如[{one:2,two:24},{one:4,two:23}]
            var counts = []; //存每种方式排列组合数
            //生成waysArr
            for (var i = 25; i >= 0; i--) {
                var x = 50 - 2 * i;
                waysArr.push({ one: x, two: i });
            }
            //阶乘
            function factorial(num) {
                if (num <= 1) {
                    return 1;
                }
                else {
                    return num * arguments.callee(num - 1);
                }
            }

            //每种方式的排列数
            //参数是走1步的次数,走2步的次数
            function thisWayTimes(one, two) {
                //排列组合公式: n!/r!(n-r)!
                //穷举--求得被除数
                var ExhaustiveTimes = factorial(one + two);
                //重复的次数---求得除数
                var repeatedTimes = factorial(one) * factorial(two);
                //算出次数---相除
                var thisWayTime = ExhaustiveTimes / repeatedTimes;
                //存进数组
                counts.push(thisWayTime);
            }

            //计算每种方式的,除去全1全2,存入数组
            for (var j = 0, waysLen = waysArr.length; j < waysLen; j++) {
                if (waysArr[j].one != 0 && waysArr[j].one != 50) {
                    thisWayTimes(waysArr[j].one, waysArr[j].two);
                }
            }

            //求和函数
            function arrayNumSum(len) {
                if (len <= 0) {
                    return 0;
                } else {
                    return counts[len] + arguments.callee(len - 1);
                }
            }

            //求和,包括全1全2
            countsSum = arrayNumSum(counts.length - 1) + 2; //计算出来共是20,365,010,749次
            alert(countsSum);
        })();

 后来正解出来,我的答案是不对,又不全错,因为排列组合公式做了除法运算,js算出来的结果不精确。

(这就是没有找到真正数学规律的方案,费力不讨好)

 

 peter.liu的思路:

 以一个台阶为迈步的单位, 每次迈步都只有三种可能: 

1.一次走完了一个台阶, 这种情况用 ‘O’表示.  (One的首字母)

2.一次走两个台阶, 但是只走到前一半, 脚还在空中悬着, 没放下. 这种情况用’T1’表示. (Two的首字母)

3.一次走两个台阶, 这次走的是后一半, 也就是脚从空中放下的过程. 这种情况用’T2’表示.

假设这个人开始走

1.走第一个台阶他有两个选择: ‘O’, 和 ‘T1’

2.走第二个台阶他的选择取决于第一个台阶怎么走的:

   a.前一个台阶如果是’O’和’T2’, 这个台阶就有两个选择: ’O’和’T1’

   b.前一个台阶如果是’T1’, 那么这个台阶就只能是’T2’.  (悬着的脚总要放下来才行啊)

3.走第三个台阶的方式, 取决于第二个台阶是怎么走的

4.走第n个台阶的方式, 取决于第n-1个台阶只怎么走的.

可以把他的每一步想象成一棵多叉树的节点, 下一步有多种走法, 那么节点就分叉. 这棵树一直到50层, 第50层有多少个叶节点, 就一共有多少种走法. 每一种走法, 都代表了从根节点到某一叶节点的那条路径.

当然, 有一个问题, 最后一层的节点类型是不能为’T1’的, 否则悬着的脚就放不下来了.

代码如下: 

(function(){

function steps(n){
    if (n === 1)
        return ['O', 'T1']; //第一步两种可能
    lastSteps = steps(n-1);
    var currentSteps = [];
    for(var i = 0; i< lastSteps.length; i++){
        var lastStep = lastSteps[i];
        if(lastStep === 'O' || lastStep === 'T2')
            currentSteps.push('O', 'T1');
        else if(lastStep === 'T1')                                              
            currentSteps.push('T2');        
    }
    return currentSteps;
}

var result = steps(20);
result = result.filter(function(item, index){return item !== 'T1'}); //最后一步不能是'T1', 过滤掉
console.log(result.length);

})();

 

最终发现, 到30层的时候, 结果已经是100多万了, 并且以指数级增长. 运算第50层的时候会卡死, 因为可能性太多运算量太大了. 

(这种思路很好,很巧妙,可惜就是运算量太大)

 

 费波拉希数列:

 peter的方法虽然不能求得50层的次数,但是可以求得前30多层。依次如下:

一共1个台阶的话有1种走法.

一共2个台阶的话有2种走法.

一共3个台阶的话有3种走法.

一共4个台阶的话有5种走法.

一共5个台阶的话有8种走法.

一共6个台阶的话有13种走法.

一共7个台阶的话有21种走法.

一共8个台阶的话有34种走法.

一共9个台阶的话有55种走法.

一共10个台阶的话有89种走法.

一共11个台阶的话有144种走法.

一共12个台阶的话有233种走法.

一共13个台阶的话有377种走法.

一共14个台阶的话有610种走法.

一共15个台阶的话有987种走法.

一共16个台阶的话有1597种走法.

一共17个台阶的话有2584种走法.

一共18个台阶的话有4181种走法.

一共19个台阶的话有6765种走法.

一共20个台阶的话有10946种走法.

一共21个台阶的话有17711种走法.

一共22个台阶的话有28657种走法.

一共23个台阶的话有46368种走法.

一共24个台阶的话有75025种走法.

一共25个台阶的话有121393种走法.

一共26个台阶的话有196418种走法.

一共27个台阶的话有317811种走法.

一共28个台阶的话有514229种走法.

一共29个台阶的话有832040种走法.

一共30个台阶的话有1346269种走法.

一共31个台阶的话有2178309种走法.

一共32个台阶的话有3524578种走法.

一共33个台阶的话有5702887种走法.

一共34个台阶的话有9227465种走法.

一共35个台阶的话有14930352种走法.

......

这不正是个费波拉希数列!!!!

 知道这个数学规律就好办了。代码如下:

        function fib(n) {
            return function(n, a, b) {
                return n > 0 ? arguments.callee(n - 1, b, a + b) : a;
            } (n, 0, 1);
        }
        fib(0); //0
        fib(1); //1
        fib(2); //1
        fib(3); //2
        fib(4); //3
        //......
        fib(50); //12586269025
        fib(51); //20365011074,这里是上到第50个阶梯

 

 我想大家会有很多其它解法,欢迎留言讨论。

 本文系原创,转载请声明出处(http://www.cnblogs.com/flowerszhong/

 

 

时间: 2024-10-23 15:13:01

腾讯面试题:50个阶梯,你一次可以上一阶或两阶,走上去,共有多少种走法【原】的相关文章

25级阶梯,每次走一步或两步,问最多有多少种走法

分析:共有25个阶梯,每一步走法共有两种,走一级,或是走两级.分两种情况:如果第一次走两级的话,那么还有25-2=23级阶梯要走.再求剩下23级阶梯共有多少走法.如果第一次走一级的话,那么还有25-1=24级阶梯要走,于是走完25级阶梯的方法总数,就等于爬完23级阶梯总共方法+爬完24级阶梯的方法总数.而23极又可再分为(23-1).(23-2)级阶梯.依次类推,可见这是一个典型的递归类型.我们可以很容易的计算出当有1级和2级阶梯的时候所有的次数:分别为1和2.于是计算方法总数的函数如下: --

一道腾讯面试题的思考:到底谁会赢?

最近看到一道腾讯面试题,觉得很有意思.题干如下:        有甲乙两家伙用一个英语单词玩游戏(无聊的人还是很多的!!!).两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序a < b < c <....<z,假设单词字母不区分大小写,也就是说,a与A算相等),则这个人胜利.假设两个人都足够聪明(即如果有赢的方案,都不会选输的方案 ),甲先开始,问他能赢么? 输入: 一连串英文小写字母,长度任意(当然要在计算机能承受的范围内),保证最开始

网站被腾讯手机管家检测危险网站,不能再浏览器上打开怎么办?求高手帮忙

问题描述 我的网站被腾讯手机管家检测危险网站,不能再浏览器上打开怎么办?求高手帮忙 解决方案 解决方案二:卸载腾讯管家解决方案三:..二楼是正解

万达腾讯百度砸50亿开电商

摘要: 8月27日,万达电商.腾讯集团内部相关负责人向21世纪经济报道确认:将于本周五召开发布会,宣布万达.百度.腾讯.万达三家公司成立电商集团,跑口万达的记者已经接到参会邀请 8月27日,万达电商.腾讯集团内部相关负责人向21世纪经济报道确认:将于本周五召开发布会,宣布万达.百度.腾讯.万达三家公司成立电商集团,跑口万达的记者已经接到参会邀请. 消息人士透露:三方对新 电子商务 公司的总投资额为人民币50亿元(约合8.10亿美元).万达持股70%,腾讯和百度各持股15%.管理架构与业务架构细节

腾讯面试题解析:重复短信问题

有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复. 有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复. 请用5分钟时间,找出重复出现最多的前10条. 分析: 常规方法是先排序,在遍历一次,找出重复最多的前10条.但是排序的算法复杂度最低为nlgn. 可以设计一个hash_table, hash_map<string, int>,依次读取一千万条短信,加载到hash_table表中,并且统计重复的次数,与此同时维护一张最多10条的短信表. 更多精彩内容:http://

腾讯面试题练习

给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数 要求下排每个数都是先前上排那十个数在下排出现的次数. 上排的十个数如下: [0,1,2,3,4,5,6,7,8,9] 举一个例子, 数值: [ 0,1,2,3,4,5,6,7,8,9 ] 分配: [ 6,2,1,0,0,0,1,0,0,0 ] 0在下排出现了6次, 1在下排出现了2次, 2在下排出现了1次, 3在下排出现了0次.... 实现代码: #include <iostream> using namespace std; c

一道腾讯面试题

view plainprint? /**    * 已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10.    */    using System;    using System. Collections.Generic;    using System.Linq;    using System.Text;        namespace  Console Application1    {        class Progr

阿里腾讯O2O积极布局,百度淡然求稳为上

今天,阿里宣布正式完成高德私有化进程,并称将开始与阿里各项业务进行全面整合.高德私有化完成意味着阿里O2O更进一步,接下来围绕高德的O2O项目可以顺利推进了. 过去1年时间,BAT三巨头都在围绕O2O做布局,尤其阿里和腾讯更为积极,近期阿里先后合并UC,私有化高德,而腾讯投资了58同城,O2O市场竞争俨然已经成为巨头们的游戏. 随着巨头们的落子逐渐增多,O2O产业链雏形已完整的呈现在公众视野,"入口+服务+支付"为O2O的主要框架,巨头们正在围绕这一框架来丰富O2O的产业链布局. 业界

窃取50万个脸书账号 美国垃圾邮件之王被判两年半监禁

据外媒报道,拉斯维加斯男子桑福德·华莱士(Sanford Wallace)是自1997年起就臭名昭著的"垃圾邮件之王",人送外号"垃圾福"(Spamford).近日"垃圾福"终于栽了,他被联邦法官判处两年半监禁并罚款31万美元,原因是他向Facebook用户发送了2700万条垃圾信息,并违反了不得访问Facebook的法院禁令. 华莱士去年承认,他窃取了约50万个Facebook账户,然后发送伪装成好友博客的垃圾广告,持续时间超过3个月. 据检察