Hulu 2020年校招-算法题《Hulu杀》Python

189 篇文章 3 订阅

已经工作了,义务支援下一届,哈哈,好久不刷题还真有点生疏。Hulu今年秋招的题目并不难,一共四个编程题,基本是在常规问题上的延伸。今天先整理第一个题目,其他题目后面有时间继续整理。

问题描述:

Hulu杀

n 个葫芦娃一起玩Hulu杀,他们被分为好人坏人两个阵营,打乱之后围成一个圈,按照顺时针序编号为 0~n-1 。然后随机选定一个葫芦娃,从他/她开始由1m顺时针报数,数到m的人被杀,下一个人继续从1报数,如此循环直到剩下最后一个人,这个人所属阵营获得胜利。我们用一个整型数组a[i]=1表示i是好人,a[i]=0表示i是坏人;整型数组w[i]表示玩家i被选为起始位置的权重,即玩家iw[i]/sum(w[i])的概率做起始位置。求好人获胜的概率,四舍五入到小数点后五位数字(不足五位需要补零)

示例 1:
输入:

# 第一行为2个空格分开的整数,分别表示n和m
# 第二行为n个空格分开的整数,表示a[i]
# 第二行为n个空格分开的整数,表示w[i]
# 输入范围0<m<n<=1000, 0<sum(w[i])<=10000000
-------------------------------------------
3 2
0 0 1
2 1 1

输出:

# 输出一个浮点数,表示好人获胜的概率
-------------------------------------------
0.50000

问题分析:

很显然,这是一个经典的约瑟夫环问题的延伸,只要在约瑟夫环问题求解基础上,加上一层映射关系即可得出答案。具体思路如下:
(1)先求出以第一个人开始,最后剩下的人(也就是约瑟夫环求解)
(2)在(1)的基础上求出每个起始位置,最后剩下的人(人)
(3)在(2)的基础上求出每个起始位置对应的是好人获胜还是坏人获胜
(4)在(3)的基础上求出每个起始位置对应的好人获胜的概率(权重求和即可),然后计算:好人获胜的概率(权重) / 总的概率(权重)即可得出答案。

注意: 输出要求应该是字符串

Python实现 AC:

# =============================================================
# !/usr/bin/python
# -*- coding=utf-8 -*-
# Name:         HuluKill
# Description:  Hulu 2020年校招 笔试题(1) -- Hulu杀
# Author:       yinxing
# Date:         2019-09-05 19:00
# =============================================================


class HuluKill:

    def JosephRing(self, n, m):

        """
        约瑟夫环问题求解
        :param n: n 个人(0, 1, 2 ... n-1)
        :param m: 每 m 人出列
        :return: 最后剩下的那个人索引
        """
        if n < 1 or m < 1: return -1

        last = 0
        for i in range(2, n+1):
            last = (last + m) % i
        return last

    def Solution(self, n, m, a, w):

        """
        获取Hulu杀的解
        :param n: n 个人(0, 1, 2 ... n-1)
        :param m: 每 m 人出列
        :param a: 好人,坏人列表
        :param w: 开始的权重
        :return: 好人队获胜的概率(保留5位小数)
        """

        victory = self.JosephRing(n, m)  # 获取选择第一个人开始,最后剩下的人(索引)

        victorylist = [(victory+i) % n for i in range(n)]  # 每个位置开始,对应获胜的人

        peoplelist = [a[victorylist[i]] for i in range(n)]  # 每个位置开始,对应胜利的人(好人,坏人)

        GoodPerson = sum([w[i] for i in range(n) if peoplelist[i] == 1])  # 好人获胜的概率(权重)

        return '%.5f' % (GoodPerson/sum(w))  # 结果 = 好人获胜的概率(权重) / 总的概率(权重)


if __name__ == '__main__':

    hulukill = HuluKill()

    # n, m = map(int, input().split())
    # a = list(map(int, input().split()))
    # w = list(map(int, input().split()))

    n, m = 3, 2
    a = [0, 0, 1]
    w = [2, 1, 1]
    print(hulukill.Solution(n, m, a, w))  # 0.50000

声明: 总结学习,有问题或不当之处,可以批评指正哦,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值