以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 C/C++编程思想 』  (http://bbs.xml.org.cn/list.asp?boardid=61)
----  google面试题[讨论]  (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=24957)


--  作者:firstway
--  发布时间:12/3/2005 1:55:00 PM

--  google面试题[讨论]

有n个人,其中超过半数是好人,剩下的是坏人
好人只说真话,坏人可能说真话也可能说假话
这n个人互相都知道对方是好人还是坏人

现在要你从这n个人当中找出一个好人来,只能通过以下方式:
每次挑出两个人,让这两个人互相说出对方的身份,
你根具两个人的话进行判断。

问通过何种方法才能最快的找出一个好人来,
(要考虑最坏的情况)


--  作者:firstway
--  发布时间:12/3/2005 3:39:00 PM

--  
我现在提一个想法,望大家指正
-------------------------
先找一个人A,然后其他所有人评价A
1如果半数说A是好人:A是好人
2如果半数以上说A是坏人:A是坏人
-----
如果A是坏人
去掉说A是好人的人(一定是坏人)
在剩下的人里找一个人重复上面的(这里好人肯定更多于一半)
---
递归进行
最坏情况就是坏人都说实,话且每次运气不好都选出的是坏人
这时复杂度是O(n平方)
实际计算时选出好人的几率越来越高的,因为坏人不断的被去掉
---
大家有何高见》?
--  作者:enorm
--  发布时间:12/3/2005 5:19:00 PM

--  
最坏的情况时所有坏人都被选出,前所有坏人说真话,这时才选出好人,最坏情况o(n^2)
最好情况o(n)

--  作者:来去如风
--  发布时间:4/23/2006 5:05:00 PM

--  google面试题-------我的解法
路过看了楼主的算法,觉得无法接受,应该是最慢的一个算法,下面是我的想法:
思想是尽量多的排除坏人:
1,如果两个人都说对方是好人,那么有两种可能,要吗都是好人,要吗都是坏人.
2,如果有一个人说对方是坏人,那么两人种至少有一个坏人,可以同时排除,剩下的人照样满足条件好人站半树以上,再在剩下的人中找好人
   int    people[] = {0,1,1,1,1,0,0,0,1};//N个人的数组1是好人,0是坏人
    int    samePos = -1, sameNum = -1;
    while(i < N - 1)
    {
        if(samePos  != -1)
        {
            if(第samePos个人和第i个人都说对方是好人)
            {
              i++;
              sameNum++;
              if(sameNum > N/2)//超过一半,肯定都是好人
              {
               return people[samePos];
              }

            }
            else
            {
                sameNum--;
                i++;
                if(sameNum == 0)
                {
                   samePos = -1;
                }
    
           }
                continue;  
        }
        
        if(第i个人和第i + 1个人都说对方是好人)
        {
           
               samePos = i;
               sameNum = 2;
        }
       else
       {
           i += 2;
       }
   }

    最后要吗剩下一个好人,要吗剩下一串好人,复杂度为o(n) ,最快n/2,最慢n.写的不太严密,请大家指正.


--  作者:天涯客
--  发布时间:7/3/2006 11:54:00 PM

--  
我的想法,前提:被选出的人可以被一直重复选出;
:如果N为偶数,所以至少有N/2个好人,取整  |好人-坏人|>=1(实际N为偶数的时候:
|好人-坏人|>=2 );好人肯定说真话,保证了结论的正确性 >=50%,
任选A,所有人评A,比较结论,评出的结果,X:好人,Y:坏人,A=X>Y?好人:坏人;
:同样的道理,N为奇数,有一样的结果。存在边界的情况:好人比坏人只多一人,X==Y;说明A为好人人。因为就算坏人都说假话,起码也有一半的真话。
所以整个算法的复杂度为 0(N).
请各位赐教!



--  作者:DavidPotter
--  发布时间:7/4/2006 4:18:00 PM

--  
l来去如风的思路不错:与查找众数的方法一样,通过不断的除去坏人与好人来利用好人超过半数的条件:如果有一个人说对方是坏人,那么两人种至少有一个坏人,可以同时排除,剩下的人照样满足条件好人站半树以上,再在剩下的人中找好人。

楼上(天涯客)的可能没有看清楚要找出好人的要求。如果A是外人的话,那么你的评选还要继续下去。


--  作者:gln
--  发布时间:7/23/2006 8:55:00 PM

--  
照来去如风的思路:如果两个人都说对方是好人,那么有两种可能,要吗都是好人,要吗都是坏人.
在此基础上,可以把这些人分为两组,A和B;
a是A组的,a和x都说对方是好人,把x加到A组,否则加到B组,,哪一组的人数先过半数了,这组就是好人,另外一组就是坏人了.
时间复杂度o(n),最快n/2,最慢n..


--  作者:cschentao
--  发布时间:8/8/2006 9:33:00 PM

--  
其实firstwai几乎谈到重点了,来去如风的分析有问题。。明天得闲写下,哈哈
--  作者:yooga
--  发布时间:7/23/2007 4:33:00 PM

--  [原创]
最慢是[n/2] + 1
最快是[n/2]
--  作者:chenminyi
--  发布时间:8/27/2007 9:59:00 AM

--  
这个好像就是算法导论上的课后习题,当时就没做出来。
--  作者:algoman
--  发布时间:8/31/2007 12:18:00 PM

--  
对于两个人都说对方是好人的情况,要么两个都是好人,要么两个都是坏人。因此可以如下操作

1)对于编号为1,2,...,n的n个人,分别按(1,2),(3,4)...这样配对(当n为奇数时有一人剩余,此人暂放一边),然后选出所有同时说对方是好人的配对。

2)若没有这样的配对.则那么由于超过一半为好人,此时所有配对均为好人与坏人配对.进而n必为奇数,且刚才配对时剩下的那个人必为好人.完毕

3)若至少有一个这样的配对,则从所有这样的配对中各抽出一个人,连同刚才可能剩下的那个人,重新组成序列 1,2,...,m(m<=ceil(n/2)).在这个新序列中超过一半为好人.则对此序列重新跳到步骤1)进行筛选

以上算法最快为O(1),最慢为O(log n)


--  作者:viperchenxi
--  发布时间:9/3/2007 10:57:00 AM

--  
哈哈,有意思啊,思考一下
--  作者:gracefullee
--  发布时间:9/10/2007 10:21:00 AM

--  
也有可能死循环啊!
好人101个,坏人100个
如果100个好人配对
100个坏人配对,坏人全部说谎话!
那么就陷入了死循环
--  作者:algoman
--  发布时间:9/15/2007 11:41:00 AM

--  
这时就应该从这100个配对中各选出1人,连同剩余的那个好人,构成新的序列重复刚才的算法。新的序列中有51个好人和50个坏人
--  作者:charloco
--  发布时间:9/20/2007 11:55:00 PM

--  
先拿出一个人依次与其他人组合,如果他被认为是坏人或好人的次数大于一半,那么他就是坏人(好人)。如果第一个人就被半数以上的人认为是好人,那么他就是好人。时间复杂度为O(n).
最坏的情况是每次挑选的人都是坏人,其他人又都指认他是坏人,这样每一次只能排除一个坏人,时间复杂度为n*k-k*(k+1)/2,应该为O(n^2)
--  作者:woofang
--  发布时间:12/2/2007 2:32:00 AM

--  google 面试题
http://www.woofang.com/google.htm
--  作者:snyyh
--  发布时间:12/10/2007 9:11:00 AM

--  
二楼不对
--  作者:affe
--  发布时间:12/14/2007 4:44:00 AM

--  
第一步:
有两排凳子两两相对
a1,...,an
b1,...,bn
如果有2n个人,就随便坐。如果有2n+1个人就,先挑一个站一边。

第二步:
ai和bi 互相说出对方的身份。i=1,..,n
如果ai和bi凳子上的人,说的不一样 和 都说对方是坏人的,两个人就搬凳子走人。(给我消失!)留ai和bi都说对方是好人的。
因为好人比坏人多,所以:如果都走人了,那最先开始站一边的就是答案。
                                   如果有剩下的人则:ai和bi凳子上的人,要么都是好人,要么都是坏人。
然后a组剩下的人中,第一个人坐最后一个人的凳子,最后一个人坐倒数第二个人的凳子,然后依次往前,第二个人坐第一个位置。
b组不动

第三步:
重复第二步
直到没有减人,则剩下的都是好人,随便找一个就是答案


--  作者:affe
--  发布时间:12/14/2007 4:52:00 AM

--  
最坏情况是:成对坏人,连续出现,并且两人还都说的一样
@:好人          #:坏人
   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
a  @  @  #  #  #  #  #  #  #  @  @  @  @  @  @
b  @  @  #  #  #  #  #  #  #  @  @  @  @  @  @

改进的方法是在第二步最后加以个随即排序,但要保持ai 和bi相对的人始终相对,比如
上面情况随机以后变成:
   1   2   3   4   5   6   7   8   9  10   11 12  13  14  15   (新)
   4   2   7   8  10  11  15   3   9   1   5  12  13   6  14   (旧)
a  #   @   #   #   @   @   @   #   #   @   #   @   @   #   @
b  #   @   #   #   @   @   @   #   #   @   #   @   @   #   @

[此贴子已经被作者于2007-12-14 5:30:55编辑过]

--  作者:yan110
--  发布时间:12/29/2007 1:48:00 PM

--  
我不会写~~
--  作者:冯诺依曼
--  发布时间:1/5/2008 6:24:00 PM

--  
考,楼上的全是高人!
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
121.094ms