一道騰訊面試題的思考:到底誰會贏?


最近看到一道騰訊面試題,覺得很有意思。題干如下:

       有甲乙兩家伙用一個英語單詞玩游戲(無聊的人還是很多的!!!)。兩個人輪流進行,每個人每次從中刪掉任意一個字母,如果剩余的字母序列是嚴格單調遞增的(按字典序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的算法,歡迎跟帖,語言不限!

 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM