一道腾讯面试题的思考:到底谁会赢?

最近看到一道腾讯面试题,觉得很有意思。题干如下:

       有甲乙两家伙用一个英语单词玩游戏(无聊的人还是很多的!!!)。两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序a < b < c <....<z,假设单词字母不区分大小写,也就是说,a与A算相等),则这个人胜利。假设两个人都足够聪明(即如果有赢的方案,都不会选输的方案 ),甲先开始,问他能赢么?

输入: 一连串英文小写字母,长度任意(当然要在计算机能承受的范围内),保证最开始的状态不是一个严格单增的序列。

输出:1表示甲可以赢,0表示甲不能赢。

例如: 输入 bad, 则甲可以删掉b或者a,剩余的是ad或者bd,他就赢了,输出1。

又如: 输入 aaa, 则甲只能删掉1个a,乙删掉一个a,剩余1个a,乙获胜,输出0。

下面给出我用Java实现的算法,如果大家有其他的实现方法,欢迎跟帖和探讨。语言不限

       我的基本实现思路将给定的单词分成若干个单调递增的序列。然后按每个序列中包含单词个数多少进行递减排序,也就是说,排在前面的单调递增序列中包含的字母个数最少。然后由甲开始从排在前面的递增序列中选择一个字母。直到该递增序列中的字母全部被选中。然后继续从下一个递增序列选择字母。按着这样的方法做,直到剩下最后一个单调递增序列,随最后选择了倒数第二个单调递增序列中的最后一个字母,谁就赢了。

例如,单词hela,可以分为三个单调递增序列:h、a、el。从甲开始选择。

甲:h

乙:a

由于a是倒数第二个单调递增序列的最后一个字母,所以乙赢了。

对于单词money可以分成三个单调递增序列:mo、n、ey。排序后:n、mo、ey。

甲:n

乙:m

甲:o

所以甲赢。

具体的实现算法如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class Test  
  2. {  
  3.     //  实现算法的方法,in为一个给定的单词  
  4.     public static int who(String in)  
  5.     {  
  6.         //  基本思路就是找到该单词中所有递增的子序列,然后从字符最少的子序列甲乙轮回删除字母,直到还剩下最后一个子序列为止  
  7.         //  谁删除了最后一个字母,谁就赢了!  
  8.           
  9.         //  in不能为null  
  10.         if(in == null)  
  11.             return 0;  
  12.         //  单词至少需要有一个字母  
  13.         if(in.length() == 0)  
  14.             return 0;  
  15.         in = in.toLowerCase();   //  都变成小写字母  
  16.         //  所有递增数列集合  
  17.         java.util.List<StringBuilder> ascendingList = new java.util.ArrayList<StringBuilder>();  
  18.         char lastChar = in.charAt(0);  
  19.           
  20.         StringBuilder sb = new StringBuilder();  // 存储当前递增的字符列表  
  21.         sb.append(lastChar);  
  22.           
  23.         for(int i = 1; i < in.length(); i++)  
  24.         {  
  25.             //  当前字符属于当前的递增序列  
  26.             if(in.charAt(i) > lastChar)  
  27.             {  
  28.                 sb.append(in.charAt(i));  
  29.             }  
  30.             //  当前字符属于下一个递增序列,所以需要存储上一个递增序列  
  31.             else  
  32.             {  
  33.                 ascendingList.add(sb);  
  34.                 sb = new StringBuilder();   
  35.                 sb.append(in.charAt(i));  
  36.             }  
  37.             lastChar = in.charAt(i);  
  38.         }  
  39.         if(sb.length() > 0)  
  40.         {  
  41.             ascendingList.add(sb);  
  42.         }  
  43.         //  下面就开始游戏了  
  44.         //  从甲开始删字母,从字符最少的递增序列开始删除第一个字母,直到之后只剩下一个递增序列为止,谁删除的最后一个之母,谁就赢了  
  45.   
  46.         //  这里本应该判断如果单词本身就是递增序列,那么甲就win了,不过既然题目说没有这种情况,所以就注释掉了  
  47.         /*if(ascendingList.size() == 1) 
  48.         { 
  49.             return 1; 
  50.         }*/  
  51.          
  52.         java.util.Collections.sort(ascendingList, new java.util.Comparator<StringBuilder>()  
  53.         {  
  54.   
  55.             @Override  
  56.             public int compare(StringBuilder sb1, StringBuilder sb2)  
  57.             {  
  58.                 if(sb1.length() > sb2.length())  
  59.                 {  
  60.                     return 1;  
  61.                 }  
  62.                 else if(sb1.length() == sb2.length())  
  63.                 {  
  64.                     return 0;  
  65.                 }  
  66.                 else   
  67.                 {  
  68.                     return -1;  
  69.                 }  
  70.                   
  71.             }  
  72.               
  73.         });  
  74.           
  75.         int win = 0;   //  1代表甲赢,0代表乙赢  
  76.   
  77.         while(ascendingList.size() > 1)  
  78.         {  
  79.             if(win == 0)  
  80.                 win = 1;    //  甲开始  
  81.             else  
  82.                 win = 0;    //  乙开始  
  83.             //  删除第一个递增序列的第一个字母,如果该递增序列  
  84.             ascendingList.get(0).delete(01);  
  85.             if(ascendingList.get(0).length() == 0)  
  86.             {  
  87.                 ascendingList.remove(0);  
  88.             }  
  89.                   
  90.         }  
  91.         return win;  
  92.     }  
  93.     public static void main(String[] args)  
  94.     {  
  95.   
  96.         System.out.println(who("money"));  
  97.   
  98.     }  
  99. }  

谁有更NB的算法,欢迎跟帖,语言不限!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值