• 算法(四)


    1     算法描述

    组委会正在为美团点评CodeM大赛的决赛设计新赛制。

    比赛有 n 个人参加(其中 n 为2的次方),每个参赛者根据资格赛和预赛、复赛的成绩,会有不同的积分。比赛采取锦标赛赛制,分轮次进行,设某一轮有 m 个人参加,那么参赛者会被分为m/2 组,每组恰好 2 人,m/2 组的人分别比赛。我们假定积分高的人肯定获胜,若积分一样,则随机产生获胜者。获胜者获得参加下一轮的资格,输的人被淘汰。重复这个过程,直至决出冠军。现在请问,参赛者A最多可以晋级到第几轮(初始为第0轮)

    2     算法分析

    本章节的算法分析包括两个步骤:用例分析与逻辑分析。

    2.1   用例分析

    用例名称

    2个参赛者

    输入

    参赛者A的积分:7

    参赛者B的积分:2

    分析步骤

    A与B比赛,A的积分比B的积分高,所以A胜利,B被淘汰,参赛者A的积分:8

    比赛结果

    参赛者A最多参加第一轮

    用例名称

    4个参赛者

    输入

    参赛者A的积分:7

    参赛者B的积分:2

    参赛者C的积分:3

    参赛者D的积分:6

    分析步骤

    第一轮:

    A与最低积分者B比赛,A胜利B被淘汰,A的积分:8

    CD比赛,D胜利C淘汰,D的积分:7

    第二轮:

    AD比赛,A胜利,D被淘汰,参赛者A的积分:9

    比赛结果

    参赛者A最多参加第二轮

    2.2   逻辑分析

    主流程算法逻辑

    • 每次比赛前对参赛者的积分排序

    • 分组比赛,让参赛者A与积分最少者比赛,A的积分最少则A在该轮次被淘汰

    • 分组比赛,其他参赛者按照积分次序与次积分低者比赛,积分高者胜利,积分低者失败,积分相同的参赛者索引值大的胜利

    • 统计晋升者的积分

    • 晋升轮次后,重复执行1的步骤

    • 比赛结束,统计输出A参加的轮次

    分组算法逻辑

    从最高积分者开始分组,2人一组,最后一名积分最低者与参赛者A比赛

    积分算法逻辑

    • 参赛者的人数是2的n次方,每轮次淘汰掉一半的参赛者

    •  胜利者每次增加1积分并且直接进入下一轮次,失败者直接被淘汰

    • 积分的最大偏移量是n,也就是,假如参赛者开始的积分是1,则进入n轮次后,其积分是1+n

    • 假设参赛者中的初始最大积分数是M,则比赛中的最大积分= M+n

    积分排序算法逻辑

    • Map-MultiThreadsSort-Reduce算法,其计算方式是:对积分列表分片-多线程执行分片排序-汇总分片排序结果-输出积分排序列表

    • 保持参赛者A在数组的索引0的位置

    比赛算法逻辑

    每轮次比赛后,按照数组的顺序移动A[n]中的胜利者到对应的主数组

    3     算法目标

    算法运行的目标是最小化系统资源开销(包括处理器资源开销与内存资源开销)以及最小耗时(算法运行时长)。

    4     算法设计

    4.1   数据结构设计

    名称

    参赛者数组积分列表

    类型

    一维数组

    长度

    参赛者的数量

    描述

    存储所有参赛者的积分数据

    4.2   算法逻辑设计

    4.2.1 genData输入数据

    1.   输入参赛者的积分列表,按照以上的数据结构标准化处理输入

    2.   积分排序sortRankFunc算法函数

    4.2.2 mainFunc函数主流程设计

    1.    对输入的参赛者按照积分高低进行排序

    2.   对输入的参赛者按照积分相同的进行分组

    3.   对输入的参赛者按照积分的高低次序进行两两分组

    4.   比赛

    5.   胜利者积分+1,更新胜利者积分

    6.   移动胜利者到指定的积分队列

    7.   淘汰失败者,设置失败者的状态

    8.   产生新的比赛轮次的参赛者,参赛者A胜利则继续执行1步骤,参赛者A失败则结束比赛执行9步骤

    9.   输出参赛者A的轮次

    4.2.3 sortRankFunc积分排序算法

    该算法使用Java Lambda表达式并行流式计算与Map-Reduce分片排序,其流程如下所示:

    1.   确定积分分片的大小

    2.   对积分分片

    3.   并行计算每片积分列表的排序

    4.   汇总合并每片排序的积分列表

    5     算法实现

    5.1   程序语言

    本程序分别使用Java语言。

    5.2   程序示例

    5.2.1 genData函数

    5.2.2 getRandomData函数

    5.2.3 mainFunc函数

    5.2.4 sortRankFunc函数

    5.2.5 mergeSort函数

    5.2.6 sortPiece函数

    5.2.7 insertSort函数

    5.2.8 seperatePieces函数

    5.2.9 normalCompute函数

    5.2.10          saveRecourceCompute函数

    5.2.11          testSort函数

    5.2.12          testPiecesSort函数

    6     算法验证

    本算法验证测试使用代码覆盖率测试方法。

    6.1   测试用例

    用例描述

    参赛人数2

    执行次数:10

    输入数列:随机数列

    输出数:最大比赛轮次

    输出值:由随机数列确定

    覆盖函数:所有函数

    用例描述

    参赛人数128

    执行次数:10

    输入数列:随机数列

    输出数:最大比赛轮次

    输出值:由随机数列确定

    覆盖函数:所有函数

    用例描述

    参赛人数1024

    执行次数:10

    输入数列:随机数列

    输出数:最大比赛轮次

    输出值:由随机数列确定

    覆盖函数:所有函数

    6.2   执行用例

    测试用例通过率100%,代码覆盖率100%。

    7     算法效率

    7.1   时间复杂度

    由代码可知该算法的时间复杂度等于O(N的多次方)。

    7.2   空间复杂度

    该算法使用一维数组,其空间复杂度是常数。

    7.3   性能测试

    输入数列长度

    输出数列长度

    耗时

    1024*1024

    14318毫秒

    1024*1024*2

    27939毫秒

    由以上的性能测试可知,每增加一个数量级范围,耗时线性增长。

    7.4   算法优化

    已启动多线程并行的处理。

    (未完待续)

  • 相关阅读:
    java for语法
    Python机器学习:Sklearn快速入门(稍微懂一些机器学习内容即可)
    IntelliJ IDEA 下.properties 中文乱码问题
    江苏建筑模板厂家-建筑模板批发供应商
    SpringBoot 开发 -- JWT 认证教程
    C++ map和set
    我为什么更推荐你使用cmake编译grpc程序?
    【旋转摆正验证码】移动积分兑换影视会员活动旋转摆正验证码识别——识别解绝方法
    【C++】类和对象 — 编译器对连续构造的优化 + 内部类(补充篇)
    立创EDA软件专业版 图示入门操作(全)
  • 原文地址:https://blog.csdn.net/uesowys/article/details/126157579