2017阿里巴巴實習生筆試題之撲克牌問題

晚上剛參加2017阿里巴巴實習生的筆試,筆試分爲兩個部分,第一部分是選擇題,第二部分是在線編程題。一做選擇題感覺就被放了一個大招,自己則是一臉懵懵的狀態:數據庫,概率,排列組合,C++,Java,數據結構,邏輯題,Linux,Android,IOS等等見過的沒見過的各種知識都涉及到了,開始的選擇題就做了很長的時間,導致後面的選擇題都是慌忙作答的。所以後面的編程題腦子也有些混亂,沒能在規定的時間內做完(連第一道編程題都沒測試就交卷了,所以我也不知道結果到底對不對)。

在這裏先說說自己對第一道編程題的理解。其中第一個編程題大概是這樣的(我沒把原題保存,大概說下意思):說一副牌不包括大小王,有4種花色,13種點數。兩個人玩這副撲克牌要制定一個新的規則——牌數隨機(可以是一個人1張,另一個人38張這樣的),然後出牌是可以出單張,兩張或者三張(多張的牌必須是同樣點數),花色不區分大小,只看點數大小(3最小,2最大;0代表10)。出牌規則是:如果第二個人手中有比第一個人更大的牌(點數更大,牌的數量需要一致,這點和我們平常玩的比較像),那就把這些更大的牌出了,如果有多種更大的牌,那就出這些牌裏較小的牌(比如第一個人出了44,第二個人有3466557778,那第二個人就得出55);如果第二個人手中沒有牌能夠比第一個人出的牌大,那就出小而且數量最多的牌(比如第一個人出了22,第二個人有4567000JJQQQ,那第二個人就出000)。

輸入兩行,第一行代表自己手上擁有的牌,第二行代表對方出的牌。
輸出一行,代表自己應該出的牌。

比如
輸入:4567000JJQQQ 22
輸出:000

[題目分析]

首先肯定是要對撲克牌做一個排序,那麼如何排序呢?肯定不能做字符串的直接比較,因爲這樣2肯定比3小,而是需要定義自己的比較規則。這就可以使用到Comparator接口了,可以定義一個代表13個點數的String數組(也可以直接用一個代表所有點數的字符串“34567890JQKA2”),在compare方法中通過比較兩個String在數組(字符串)中的索引得到這兩個String的相對大小。

在排序完之後,可以通過分析對方出牌的點數p1和數量c1,去自己排序的手牌中尋找有沒有合適的牌。我的想法是在遍歷手牌的過程中將所有的點數放進一個LinkedHashSet中,得到不重複而且有序的點數。然後依次遍歷這個LinkedHashSet,計算我方當前點數p2的數量c2,並比較p1和p2的大小。如果我方的點數比對方的點數小,那麼就尋找長度最長且較小的點數;如果我方的點數比對方的點數大,那麼比較數量c1和c2,如果我方在此點數的數量和對方數量相同甚至更大,那麼就找到了比對方大且代價較小的牌。

具體代碼實現如下:


import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

class ComparePoker implements Comparator<String>{

    /**
     * 查找點數索引,索引越大表示點數越大
     * @param key
     * @return
     */
    public static int indexOfArray(String key){
        //從小到大排序的點數
        final String[] points = 
            {"3","4","5","6","7","8","9","0","J","Q","K","A","2"};

        int index = 0;
        for(String str : points){
            index ++;
            if(str.equals(key)){
                return index;
            }
        }
        return -1;
    }

    /**
     * 若p1<p2則返回-1,相等則返回0,否則返回1
     */
    @Override
    public int compare(String p1, String p2) {
        // TODO Auto-generated method stub
        if(indexOfArray(p1) > indexOfArray(p2)){
            return 1;
        }
        else if(indexOfArray(p1) < indexOfArray(p2)){
            return -1;
        }else{
            return 0;
        }
    }
}


public class Main {

    /**
     * 處理手牌,找出應該出的牌
     * @param pocket
     * @param card
     * @return
     */
    String process(String pocket, String card) {
        List<String> pocketlist = StringtoList(pocket);
        List<String> cardlist = StringtoList(card);
        Collections.sort(pocketlist,new ComparePoker());//對自己手牌排序
//      Collections.sort(cardlist,new ComparePoker());//無需排序
        return findCard(pocketlist, cardlist);
    }

    /**
     * 找最合適的牌
     * @param myList
     * @param otherlist
     * @return
     */
    String findCard(List<String> myList,List<String> otherlist){
        //統計對方出牌信息
        int otherlength = otherlist.size();
        String othercard = otherlist.get(otherlength-1);
        int otherindex = ComparePoker.indexOfArray(othercard);

        //統計自己手牌點數
        HashSet<String> hashSet = new LinkedHashSet<>();
        for(String string : myList){
            hashSet.add(string);
        }
        Iterator<String> iterator = hashSet.iterator();

        int max = 0;//最終長度
        String finalstr = "";//最終單個點數信息

        while(iterator.hasNext()){
            //分析自己手牌點數信息
            String str = iterator.next();
            int myindex = ComparePoker.indexOfArray(str);
            int mylength = myList.lastIndexOf(str)-myList.indexOf(str)+1;

            if(myindex <= otherindex){//自己點數比對方點數小的情況,找最長且較小的牌
                if(mylength > max){
                    max = mylength;
                    finalstr = str;
                }
            }else{
                if(mylength >= otherlength){//自己點數比對方點數大的情況,只需找到長度>=對方長度的點數即可
                    max = otherlength;
                    finalstr = str;
                    break;
                }
            }
        }

        //根據牌的長度和點數決定出牌信息
        StringBuffer stringBuffer = new StringBuffer();
        for(int i = 0 ; i < max ; i++){
            stringBuffer.append(finalstr);
        }
        return stringBuffer.toString();
    }

    /**
     * 分割字符串
     * @param string
     * @return
     */
    List<String> StringtoList(String string){
        List<String> list = new ArrayList<>();
        char[] array = string.toCharArray();
        for(char s : array){
            list.add(String.valueOf(s));
        }
        return list;
    }

    /**
     * 主函數
     * @param args
     */
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        String res;

        String regex = "[34567890JQKA2]+";
        String _pocket;
        try {
            _pocket = in.nextLine();
            if (!_pocket.replaceAll(regex, "").equals("")) {//判斷是不是指定的牌
                return;
            }
        } catch (Exception e) {
            _pocket = null;
        }

        String _card;
        try {
            _card = in.nextLine();
            if (!_card.replaceAll(regex, "").equals("")) {//判斷是不是指定的牌
                return;
            }
        } catch (Exception e) {
            _card = null;
        }

        Main mainclass = new Main();
        res = mainclass.process(_pocket, _card);
        System.out.println(res);
    }

}

只是爲了實現功能,代碼比較粗糙且未經過阿里系統測試,僅分享自己的想法供參考。作爲編程菜鳥,經過這次的筆試後發現不足的地方太多太多了,還需要不斷地改進和提升。這裏附上自己曾經寫過的一個小小的撲克牌程序:Java入門第三季–簡易撲克牌遊戲

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章