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


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

           有甲乙两家伙用一个英语单词玩游戏(无聊的人还是很多的!!!)。两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序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

    所以甲赢。

    具体的实现算法如下:

    public class Test
    {
        //  实现算法的方法,in为一个给定的单词
    	public static int who(String in)
    	{
    		//  基本思路就是找到该单词中所有递增的子序列,然后从字符最少的子序列甲乙轮回删除字母,直到还剩下最后一个子序列为止
    		//  谁删除了最后一个字母,谁就赢了!
    		
    		//  in不能为null
    		if(in == null)
    			return 0;
    		//  单词至少需要有一个字母
    		if(in.length() == 0)
    			return 0;
    		in = in.toLowerCase();   //  都变成小写字母
    		//  所有递增数列集合
    		java.util.List<StringBuilder> ascendingList = new java.util.ArrayList<StringBuilder>();
    		char lastChar = in.charAt(0);
    		
    		StringBuilder sb = new StringBuilder();  // 存储当前递增的字符列表
    		sb.append(lastChar);
    		
    		for(int i = 1; i < in.length(); i++)
    		{
    			//  当前字符属于当前的递增序列
    			if(in.charAt(i) > lastChar)
    			{
    				sb.append(in.charAt(i));
    			}
    			//  当前字符属于下一个递增序列,所以需要存储上一个递增序列
    			else
    			{
    				ascendingList.add(sb);
    				sb = new StringBuilder(); 
    				sb.append(in.charAt(i));
    			}
    			lastChar = in.charAt(i);
    		}
    		if(sb.length() > 0)
    		{
    			ascendingList.add(sb);
    		}
    		//  下面就开始游戏了
    		//  从甲开始删字母,从字符最少的递增序列开始删除第一个字母,直到之后只剩下一个递增序列为止,谁删除的最后一个之母,谁就赢了
    
    		//  这里本应该判断如果单词本身就是递增序列,那么甲就win了,不过既然题目说没有这种情况,所以就注释掉了
    		/*if(ascendingList.size() == 1)
    		{
    			return 1;
    		}*/
    	   
    		java.util.Collections.sort(ascendingList, new java.util.Comparator<StringBuilder>()
    		{
    
    			@Override
    			public int compare(StringBuilder sb1, StringBuilder sb2)
    			{
    				if(sb1.length() > sb2.length())
    				{
    					return 1;
    				}
    				else if(sb1.length() == sb2.length())
    				{
    					return 0;
    				}
    				else 
    				{
    					return -1;
    				}
    				
    			}
    			
    		});
    		
    		int win = 0;   //  1代表甲赢,0代表乙赢
    
    		while(ascendingList.size() > 1)
    		{
    			if(win == 0)
    			    win = 1;    //  甲开始
    			else
    				win = 0;    //  乙开始
    			//  删除第一个递增序列的第一个字母,如果该递增序列
    			ascendingList.get(0).delete(0, 1);
    			if(ascendingList.get(0).length() == 0)
    			{
    				ascendingList.remove(0);
    			}
    				
    		}
    		return win;
    	}
    	public static void main(String[] args)
    	{
    
    		System.out.println(who("money"));
    
    	}
    }
    

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

    2013 CSDN博客之星评选

     
     
  • 相关阅读:
    vs code 编译python 输出到调试控制台
    vs code个性化设置
    IDEA 简拼输入
    微信小程序 audio组件 默认控件 无法隐藏/一直显示/改了controls=‘false’也没用2019/5/28
    win10的cortana搜索显示空白
    微信小程序tabbar不显示2019.04.06
    读《提问的智慧》有感
    CLion 控制台输出内容乱码问题的解决方法
    vs code C语言环境搭建
    利用python的爬虫技术爬去糗事百科的段子
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3476351.html
Copyright © 2020-2023  润新知