• 传球问题


    传球问题

    问题描述

    A,B,C,D,E 五个人互相传球,由 A 开始第一次传球,经 5 次传球后传回到 A 的手上,其中 A 与 B 不会相互传球,C 只会传给 D,E 不会传给 C,共有多少种传法?

    分析问题

    按照问题的描述可以画出如下的有向图:

    传球的模式可以简化为:

    A -> □ -> □ -> □ -> □ -> A

    实际上可以把它看成一个路径问题,从 A 出发,最终又回到 A。
    根据限定条件,尝试不同的路径,经过 5 次传球后,如果能够到达 A,就说明这次尝试的路径是正确的。

    可以尝试递归加上回溯解决这个问题。(似乎和找迷宫出路是一样的)

    编写代码

    使用 ECMAScript 6 编写, node v8.9.4 编译运行。

    首先设计一个 Person 类,用来构造 A,B,C,D,E 五个对象。他们内部有一个数组 ableToNext,用来存放可以传球的对象。

    class Person {
        constructor(name) {
            this.name = name;
            this.ableToNext = new Array();
        }
    }
    

    此外有个 persons 对象,存放 5 个人和当前拥有球的人。然后根据当前拥有球的人中存有的 ableToNext 数据,将球传给下一个人,递归地找出所有的可能情况。用一个数组 ballStack 作为栈,用来保存传球的情况。因此栈的大小就是传球的次数。

    递归函数 passBall 为:

    function passBall(person) {
        person.ableToNext.forEach( next => {
            // /*
            if( ballStack.length < (MaxBallPassCount - 1) && next == persons.finalOwner ) {
                // finalOwner doesn't get the ball at the meantime
                return;
            }
            // */
            attmptCount++;
            ballStack.push( next.name );
            persons.ballOwner = next;
            // log( ballStack.length +": "+ next+ "  " );
            passBall(next);
        });
        // all possiblility have been attempted, get back to last one
        ballStack.pop();
    }
    

    递归终止的条件是传球 5 次。如果传球的次数达到了 5 次,那么当前拥有球的人就不必继续传球了。

    // end condition of recursive
    if( ballStack.length == MaxBallPassCount ) {
        if( persons.ballOwner == persons.finalOwner ) {
            validCount++;
            console.log( validCount, ballStack );
        }
        ballStack.pop();
        return;
    }
    

    在这里会把所有有效的情况打印出来。不过对于这个问题,由于在 5 次传球的过程中,A 是可以在中间出现的,所以递归函数应该是这样的:

    function passBall(person) {
        ...
        person.ableToNext.forEach( next => {
            attmptCount++;
            ballStack.push( next.name );
            persons.ballOwner = next;
            // log( ballStack.length +": "+ next+ "  " );
            passBall(next);
        });
        ...
    }
    

    这样得到的有效情况是 30 种:

    如果说在前 4 次传球过程中,球不能传到 A,那么有效情况是 18 种:

    总结

    这个问题比较简单,核心内容就是递归函数,最后只要根据限定的次数结束递归就可以得到所有的情况了。

    还有 一种思路 是找出所有可能的情况,再根据限制条件进行过滤。

    详细的代码在 Github

  • 相关阅读:
    大数据集群迁移的那一夜是怎么过的
    什么是Lambda架构
    从0到1搭建自助分析平台
    业务重要?还是技术重要?
    如何从0到1搭建大数据平台
    从0到1搭建大数据平台之数据采集系统
    高频面试题:秒杀场景设计
    面试官:面对千万级、亿级流量怎么处理?
    来自朋友最近阿里、腾讯、美团等P7岗位面试题
    《我想进大厂》之JVM夺命连环10问
  • 原文地址:https://www.cnblogs.com/brifuture/p/9258076.html
Copyright © 2020-2023  润新知