整理扑克牌----给定一组数字,表示扑克牌的牌面数字,忽略扑克牌的花色,请按如下规则对这一组扑克牌进行整理

目录

题目描述

步骤1、对扑克牌进行分组,形成组合牌,规则如下

步骤2、对上述组合牌进行由大到小排列,规则如下

步骤3、当存在多个可能组合方案时,按如下规则排序取最大的一个组合方案

输入描述

输出描述

题目分析

思路分析

1、数据分类

2、添加数据

3、添加葫芦

4、对葫芦进行排序

5、输出

完整代码

题目描述

给定一组数字,表示扑克牌的牌面数字,忽略扑克牌的花色,请按如下规则对这一组扑克牌进行整理:

  • 步骤1、对扑克牌进行分组,形成组合牌,规则如下

  1. 1. 当牌面数字相同张数大于等于4 时,组合牌为“炸弹”;
  2. 2. 3 张相同牌面数字+2 张相同牌面数字,且3 张牌与2 张牌不相同时,组合牌为“葫芦”;
  3. 3. 3 张相同牌面数字,组合牌为“三张”;
  4. 4. 2 张相同牌面数字,组合牌为“对子”;
  5. 5. 剩余没有相同的牌,则为“单张”;

步骤2、对上述组合牌进行由大到小排列,规则如下

  1. 1. 不同类型组合牌之间由大到小排列规则:“炸弹” > "葫芦" > "三张" > "对子" >“单张”;
  2. 2. 相同类型组合牌之间,除“葫芦”外,按组合牌全部牌面数字加总由大到小排列;
  3. 3. “葫芦”则先按3 张相同牌面数字加总由大到小排列,3 张相同牌面数字加总相同时,再按另外2 张牌面数字加总由大到小排列;
  4. 4. 由于“葫芦”>“三张”,因此如果能形成更大的组合牌,也可以将“三张”拆分为2 张和1 张,其中的2 张可以和其它“三张”重新组合成“葫芦”,剩下的1 张为“单张”

步骤3、当存在多个可能组合方案时,按如下规则排序取最大的一个组合方案

  1. 1. 依次对组合方案中的组合牌进行大小比较,规则同上;
  2. 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, 53, 3, 3, 3
葫芦6, 6, 6, 3, 32, 2, 2, 8, 8
6, 6, 6, 3, 36, 6, 6, 2, 2
三张7, 7, 76, 6, 6
对子8, 83, 3
单张1310

思路分析

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;
            //循环2
            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]);
            }
        }

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,小于时返回-1
                    return 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 + " ");
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值