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入门第三季–简易扑克牌游戏

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值