扑克牌"/>
整理扑克牌
目录
题目描述
步骤1、对扑克牌进行分组,形成组合牌,规则如下
步骤2、对上述组合牌进行由大到小排列,规则如下
步骤3、当存在多个可能组合方案时,按如下规则排序取最大的一个组合方案
输入描述
输出描述
题目分析
思路分析
1、数据分类
2、添加数据
3、添加葫芦
4、对葫芦进行排序
5、输出
完整代码
题目描述
给定一组数字,表示扑克牌的牌面数字,忽略扑克牌的花色,请按如下规则对这一组扑克牌进行整理:
-
步骤1、对扑克牌进行分组,形成组合牌,规则如下
- 1. 当牌面数字相同张数大于等于4 时,组合牌为“炸弹”;
- 2. 3 张相同牌面数字+2 张相同牌面数字,且3 张牌与2 张牌不相同时,组合牌为“葫芦”;
- 3. 3 张相同牌面数字,组合牌为“三张”;
- 4. 2 张相同牌面数字,组合牌为“对子”;
- 5. 剩余没有相同的牌,则为“单张”;
步骤2、对上述组合牌进行由大到小排列,规则如下
- 1. 不同类型组合牌之间由大到小排列规则:“炸弹” > "葫芦" > "三张" > "对子" >“单张”;
- 2. 相同类型组合牌之间,除“葫芦”外,按组合牌全部牌面数字加总由大到小排列;
- 3. “葫芦”则先按3 张相同牌面数字加总由大到小排列,3 张相同牌面数字加总相同时,再按另外2 张牌面数字加总由大到小排列;
- 4. 由于“葫芦”>“三张”,因此如果能形成更大的组合牌,也可以将“三张”拆分为2 张和1 张,其中的2 张可以和其它“三张”重新组合成“葫芦”,剩下的1 张为“单张”
步骤3、当存在多个可能组合方案时,按如下规则排序取最大的一个组合方案
- 1. 依次对组合方案中的组合牌进行大小比较,规则同上;
- 2. 当组合方案A 中的第n 个组合牌大于组合方案B 中的第n 个组合牌时,组合方案A 大于组合方案B;
输入描述
第一行为空格分隔的N 个正整数,每个整数取值范围[1,13],N 的取值范围[1,1000]
输出描述
经重新排列后的扑克牌数字列表,每个数字以空格分隔
题目分析
共有五种牌型:
牌型 | 举例 |
炸弹 | 4, 4, 4, 4 |
葫芦 | 2, 2, 2, 3, 3 |
三张 | 6, 6, 6 |
对子 | 9, 9 |
单张 | 10 |
大小关系:炸弹 > 葫芦 > 三张 > 对子 > 单张
牌型 | 大 | 小 |
炸弹 | 5, 5, 5, 5 | 3, 3, 3, 3 |
葫芦 | 6, 6, 6, 3, 3 | 2, 2, 2, 8, 8 |
6, 6, 6, 3, 3 | 6, 6, 6, 2, 2 | |
三张 | 7, 7, 7 | 6, 6, 6 |
对子 | 8, 8 | 3, 3 |
单张 | 13 | 10 |
思路分析
1、数据分类
建立五个集合,分别存储,炸弹、葫芦、三张、对子、单张
2、添加数据
对数组进行排序,在首次循环中,无法直接添加葫芦,所以先将数据添加为4类,具体方式为,利用两个for循环,当循环2中的数据等于循环1中的数据时,count++,当不等于时退出循环2,(注意:此时需要根据 count 的值重新设定 i 的值)
当 count > 4 时,根据题意,可输入1000个数字,所以每种牌不一定只有 4 张,所以利用 count / 4 的值作为向炸弹集合中添加的计数值,每次添加 4 个,同时,如果 4 个 4 个的向炸弹集合添加没有添加完时,需要将剩下的添加到其他的集合中
当 count == 3 或 count == 2 或 count == 1 时,分别向不同的集合中添加数据即可
//循环1
for (int i = 0; i < poke.length; i++) {int count = 1;//循环2for (int j = i + 1; j < poke.length; j++) {if (poke[j] == poke[i]) {count++;} else {break;}}i += count - 1;if (count / 4 > 0) {for (int j = 0; j < (count / 4) * 4; j++) {zha.add(poke[i]);}count %= 4;}if (count == 3) {for (int j = 0; j < 3; j++) {san.add(poke[i]);}}if (count == 2) {for (int j = 0; j < 2; j++) {dui.add(poke[i]);}}if (count == 1) {dan.add(poke[i]);}}
3、添加葫芦
为了满足“步骤3”中“2”的要求,用最小的“对子”匹配最大的“三张”成为“葫芦”,这就要对集合进行排序( sort()方法 )
只有存在“三张”的时候才需要添加葫芦,分为两种情况
a、当存在“对子”时,直接用大“三张”匹配小“对子”
b、当不存在“对子”时,当且仅当剩余未分配的“三张”大于等于 2 组时,才需要将较小的一组三张拆成一个“对子”和一个“单张”,将“对子”和“三张”组合成“葫芦”,将“单张”添加到单张集合中,由于此处单张集合可能会进行添加操作,且在添加“葫芦”的同时无需用到“单张”,所以在添加完“葫芦”之后再对“单张”进行排序
为了便于对集合进行操作,定义 left 从三张的左侧左开始遍历,定义right 从三张的右侧开始遍历,定义duiIndex从“对子”的右侧开始遍历
zha.sort((o1, o2) -> o2 - o1);san.sort((o1, o2) -> o2 - o1);dui.sort((o1, o2) -> o2 - o1);int left = 0;int right = san.size() - 1;int duiIndex = dui.size() - 1;while (right - left >= 2) {if (duiIndex > 0) {hulu.add(new int[]{san.get(left++), san.get(left++), san.get(left++), dui.get(duiIndex--), dui.get(duiIndex--)});} else {while (right - left >= 5) {hulu.add(new int[]{san.get(left++), san.get(left++), san.get(left++), san.get(right--), san.get(right--)});dan.add(san.get(right--));}break;}}
4、对葫芦进行排序
对两个“葫芦”逐张进行比较,比较出大小
hulu.sort((o1, o2) -> {for (int i = 0; i < o1.length; i++) {if (o1[i] != o2[i]) {//此处的相减操作一定不会超出int的范围,所以可以直接返回o2[i] - o1[i],当可能出现越界的情况时,一定要按标准写,大于时返回1,小于时返回-1return o2[i] - o1[i];}}return 0;});
5、输出
输出时,炸弹、葫芦、单张都直接进行遍历即可,但是三张和对子要考虑前面定义的left、right、duiIndex的值
完整代码
public class ArrangePoke {public static void main(String[] args) {/* 测试用例int[] arr = new int[]{4, 7, 6, 7, 4, 4, 6, 7, 2, 1, 2, 6, 4, 4, 4, 4};int[] arr = new int[]{9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1};*/int[] arr = new int[]{9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};method(arr);}public static void method(int[] poke) {Arrays.sort(poke);ArrayList<Integer> zha = new ArrayList<>();ArrayList<int[]> hulu = new ArrayList<>();ArrayList<Integer> san = new ArrayList<>();ArrayList<Integer> dui = new ArrayList<>();ArrayList<Integer> dan = new ArrayList<>();for (int i = 0; i < poke.length; i++) {int count = 1;for (int j = i + 1; j < poke.length; j++) {if (poke[j] == poke[i]) {count++;} else {break;}}i += count - 1;if (count / 4 > 0) {for (int j = 0; j < (count / 4) * 4; j++) {zha.add(poke[i]);}count %= 4;}if (count == 3) {for (int j = 0; j < 3; j++) {san.add(poke[i]);}}if (count == 2) {for (int j = 0; j < 2; j++) {dui.add(poke[i]);}}if (count == 1) {dan.add(poke[i]);}}zha.sort((o1, o2) -> o2 - o1);san.sort((o1, o2) -> o2 - o1);dui.sort((o1, o2) -> o2 - o1);int left = 0;int right = san.size() - 1;int duiIndex = dui.size() - 1;while (right - left >= 2) {if (duiIndex > 0) {hulu.add(new int[]{san.get(left++), san.get(left++), san.get(left++), dui.get(duiIndex--), dui.get(duiIndex--)});} else {while (right - left >= 5) {hulu.add(new int[]{san.get(left++), san.get(left++), san.get(left++), san.get(right--), san.get(right--)});dan.add(san.get(right--));}break;}}dan.sort((o1, o2) -> o2 - o1);hulu.sort((o1, o2) -> {for (int i = 0; i < o1.length; i++) {if (o1[i] != o2[i]) {return o2[i] - o1[i];}}return 0;});for (int item : zha) {System.out.print(item + " ");}for (int[] items : hulu) {for (int item : items) {System.out.print(item + " ");}}for (int i = left; i <= right; i++) {System.out.print(san.get(left) + " ");}for (int i = 0; i <= duiIndex; i++) {System.out.print(dui.get(i) + " ");}for (int item : dan) {System.out.print(item + " ");}}
}
更多推荐
整理扑克牌
发布评论