名人问题 算法解析与Python 实现 O(n) 复杂度 (以Leetcode 277. Find the Celebrity为例)
1. 题目描述 Problem Description
Leetcode 277. Find the Celebrity
Suppose you are at a party with
npeople (labeled from0ton - 1) and among them, there may exist one celebrity. The definition of a celebrity is that all the othern - 1people know him/her but he/she does not know any of them.Now you want to find out who the celebrity is or verify that there is not one. The only thing you are allowed to do is to ask questions like: "Hi, A. Do you know B?" to get information of whether A knows B. You need to find out the celebrity (or verify there is not one) by asking as few questions as possible (in the asymptotic sense).
You are given a helper function
bool knows(a, b)which tells you whether A knows B. Implement a functionint findCelebrity(n), your function should minimize the number of calls toknows.Note: There will be exactly one celebrity if he/she is in the party. Return the celebrity's label if there is a celebrity in the party. If there is no celebrity, return
-1.
2. 题目解析(参考了Prof. Sarrafzadeh 180讲的内容)
首先题目定义了:如果一个人A是名人,那么其他的n-1个人都认识A,而且A不认识其他的n-1个人。这题的目标是要从n个人中找出其中的名人,如果没有,则告知其中没有名人。我们可以调用knows(a,b)函数来询问a是否认识b,而我们要尽量少调用这个函数。
这题的关键是理解题意,题意其实比较容易理解错,所以有几个小问题可以帮大家理解:
(1)n个人中最多可以有几个名人?
答案:是1个。如果这n个人中有2个名人分别为A和B,那么按照定义,如果一个人A是名人,那么其他的n-1个人都认识A,而且A不认识其他的n-1个人,这也就是说A不认识B。但与此同时我们又定义了如果一个人B是名人,那么其他的n-1个人都认识B,那么A也应该认识B。这就产生了 contradiction了。因此其中不可以有2个或2个以上的名人。
(2) 如果其他n-1个人都认识A,但是A认识了n-1个人中其中一个人,那么A还是名人吗?
答案:不是的。
(3) 如果A不认识其他的n-1个人,但是n-1个人中有人不认识A,那么A还是名人吗?
答案:不是的。
-
这题最直接的想法应该是暴力,但是暴力的复杂度是多少呢?对于每个人我们需要询问:
(1) 他是否认识剩下的n-1个人: 最坏的情况需要调用knows(a,b)函数n-1次
(2) 剩下的n-1个人是否认识他:最坏的情况需要调用knows(a,b)函数n-1次
有的可能会重复,但是总体来说需要询问的次数是$\frac{n(n-1)}{2}$。即时间复杂度为 O($n^2$)
-
有没有办法优化算法?
如果我们从n个人中任意挑两个人a,b出来,询问啊是否认识b,那么只有两种情况:
(1)a认识b:那么a肯定不是名人。
(2)b认识a:那么b肯定不是名人。
所以任何一种情况,我们都可以排除掉2个人中的1一个人。如果我们不断地重复的这个过程,直到只剩下一个人,那么我们会做n-1次对比。而剩下这个人是唯一可能成为名人的人,那么我们需要询问剩下的n-1个人是否认识他,也需要询问他是否认识剩下的n-1个人。
因此我们一共需要询问3(n-1)次——时间复杂度为O($n$)。
3. Python 实现
# The knows API is already defined for you.
# @param a, person a
# @param b, person b
# @return a boolean, whether a knows b
# def knows(a, b):
class Solution(object):
def findCelebrity(self, n):
"""
:type n: int
:rtype: int
"""
if n == 0:
return -1
curr_stay = 0
for i in range(1, n):
if knows(curr_stay, i):
curr_stay = i
for i in range(0, n):
if i == curr_stay:
continue
if knows(curr_stay, i):
return -1
if not knows(i, curr_stay):
return -1
return curr_stay
名人问题 算法解析与Python 实现 O(n) 复杂度 (以Leetcode 277. Find the Celebrity为例)的更多相关文章
- DeepFM算法解析及Python实现
1. DeepFM算法的提出 由于DeepFM算法有效的结合了因子分解机与神经网络在特征学习中的优点:同时提取到低阶组合特征与高阶组合特征,所以越来越被广泛使用. 在DeepFM中,FM算法负责对一阶 ...
- GBDT+LR算法解析及Python实现
1. GBDT + LR 是什么 本质上GBDT+LR是一种具有stacking思想的二分类器模型,所以可以用来解决二分类问题.这个方法出自于Facebook 2014年的论文 Practical L ...
- FM算法解析及Python实现
1. 什么是FM? FM即Factor Machine,因子分解机. 2. 为什么需要FM? 1.特征组合是许多机器学习建模过程中遇到的问题,如果对特征直接建模,很有可能会忽略掉特征与特征之间的关联信 ...
- Bayesian Personalized Ranking 算法解析及Python实现
1. Learning to Rank 1.1 什么是排序算法 为什么google搜索 ”idiot“ 后,会出现特朗普的照片? “我们已经爬取和存储了数十亿的网页拷贝在我们相应的索引位置.因此,你输 ...
- FFM算法解析及Python实现
1. 什么是FFM? 通过引入field的概念,FFM把相同性质的特征归于同一个field,相当于把FM中已经细分的feature再次进行拆分从而进行特征组合的二分类模型. 2. 为什么需要FFM? ...
- [leetcode]277. Find the Celebrity 找名人
Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...
- [LeetCode] 277. Find the Celebrity 寻找名人
Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...
- [leetcode]277. Find the Celebrity谁是名人
Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...
- python常见排序算法解析
python——常见排序算法解析 算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法 ...
随机推荐
- iOS之创建通知、发送通知和移除通知的坑
1.创建通知,最好在viewDidLoad的方法中创建 - (void)viewDidLoad { [super viewDidLoad]; //创建通知 [[NSNotificationCenter ...
- grid 布局的使用
grid 布局的使用 css 网格布局,是一种二维布局系统. 浏览器支持情况:老旧浏览器不支持, 概念: 网格容器.元素应用dispalay:grid,它是所有网格项的父元素. <div cla ...
- 个人免签即时到账收款接口 bufpay.com 支持多账号收款
有很多 bufpay 的用户反馈,单个手机收款有些时候不太方便,切换手机太麻烦:或者是营业额比较多,希望分摊到多个账号上面. 基于以上的问题,bufpay 开发了多手机收款的功能:每个收款的手机安装 ...
- chromium之ref_counted
namespace subtle { class RefCountedBase { protected: RefCountedBase(); ~RefCountedBase(); void AddRe ...
- pom.xml文件报MavenArchiver错误 org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.MavenProject, org.apache.maven.archiver.MavenArchiveConfiguration)
第一种方式 war项目 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId> ...
- 【转】Red5流服务器搭建(实现在线直播,流媒体视频播放和在线视频会议)
来自:http://blog.csdn.net/sunroyi666/article/details/52981639 一. 先介绍一下流媒体技术:所谓流媒体技术,是指将连续的影像和声音信息经过压缩处 ...
- C语言程序设计:现代方法(第2版)第二章全部习题答案
前言 本人在通过<C语言程序设计:现代方法(第2版)>自学C语言时,发现国内并没有该书完整的课后习题答案,所以就想把自己在学习过程中所做出的答案分享出来,以供大家参考.这些答案是本人自己解 ...
- Docker开篇之HelloWorld
按照程序世界的惯例,我们应该以HelloWorld的程序为起点开始介绍.那么接下来我们就看看Docker的HelloWorld是如何运行的. 安装 Docker CE 由于我的系统是OSX,个人推荐使 ...
- vuetify.js框架 下拉框数据改变DOM原数据未清除
今天遇到一个奇怪的bug 需求很简单,就是将“引擎能力”下拉框选中的值作为筛选条件传入到“样本类型”下拉框中,默认“样本类型”下拉框显示所有样本类型 看图: 如图所示,功能很简单. 其实还是对vuet ...
- 20145209 2016-2017-2 《Java程序设计》第4周学习总结
20145209 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 继承是面向对象最显著的一个特性.继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性 ...