晚上剛參加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入門第三季–簡易撲克牌遊戲。