晚上刚参加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入门第三季–简易扑克牌游戏。