华为笔试算法:清一色胡牌问题(java)

2023-05-16

题目描述
清一色是麻将番种之一,指由一种花色的序数牌组成的和牌。数字1-9,每个数字最多有4张牌。我们不考虑具体花色,我们只看数字组合。
刻子:三张一样的牌;如: 111, 222, 333, ..., 999
顺子:三张连续的牌;如: 123, 234, 345, ..., 789
对子:两张相同的牌;如: 11, 22, 33, ..., 99
需要实现一个程序,判断给定牌,是否可以和牌(胡牌)。
和牌要求
- 麻将牌张数只能是 2, 5, 8, 11, 14
- 给定牌可以组合成,除1个对子以外其他都是刻子或顺子
举例

- "11"                    -> "11", 1对子,可以和牌
- "11122233"        -> "111"+"222"+"33", 2刻子,1对子,可以
- "11223344567"  -> "11"+"234"+"234"+"567", 1对子,3顺子,可以
                             -> "123"+"123"+"44"+"567", 另一种组合,也可以
输入描述:
合法C字符串,只包含'1'-'9',且已经按从小到大顺序排好;字符串长度不超过15。同一个数字最多出现4次,与实际相符。
输出描述:
C字符串,"yes"或者"no"
示例1
输入:2244

输出:no
————————————————

思路

先找刻子,再找顺子,找到顺子或刻子,则递归调用。剩下两张如果是对子,则胡牌

以下为具体代码(含分析)

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()) {
            String string = sc.nextLine();
            if(string.isEmpty()){
                System.out.println("请重新输入!");
                continue;
            }
            boolean matches = string.matches("[1-9]+");
            if(!matches){
                System.out.println("非法输入, 请重新输入!");
                continue;
            }
            int length = string.length();
            if(length != 2 && length != 5 && length != 8 && length != 11 && length != 14 ){
                System.out.println("no!");
                continue;
            }
            String[] split = string.split("");
            if(length == 2 && split[0] == split[1]){
                System.out.println("yes!");
                continue;
            }
            LinkedList<Integer> list = new LinkedList<>(Arrays.asList(split)
                    .stream().map(Integer::valueOf).collect(Collectors.toList()));
            boolean result = fun(list);
            System.out.println(result ? "yes" : "no");
        }
    }

    /**
     * 解析:
     * 1. 判断只剩对子的情况
     * 2. 先判断有没有刻子?
     *   2.1. 如果没有,则循环结束开始查询有没有顺子;
     *   2.2. 如果有,删除刻子元素后递归调用;
     *      2.2.1. 递归返回true, 则证明可以胡牌,继续返回即可;
     *      2.2.2. 递归返回false, 则恢复刚刚删除的刻子元素并跳出循环,让其找顺子
     *      依次递归...
     * 3. 判断有没有顺子?
     *   3.1. 如果没有,则循环结束自动返回false;
     *   3.2. 如果有,则删除顺子元素后递归调用;
     *      3.2.1. 递归返回true, 则可以胡牌,继续返回false即可
     *      3.2.2. 递归返回false, 则恢复刚刚删除的顺子元素,顺延开始元素换其他顺子方案继续查找
     *      (eg: "12344", 上次从链表最后一个开始找,找到234,剩下14,无法胡牌;
     *           则恢复删除的234,从列表的倒数第二个开始找顺子;
     *           依次顺延,最后找到123,剩下44)
     *
     * @param list
     * @return
     */
    private static boolean fun(LinkedList<Integer> list) {
        if(list.size() == 2){
            if(list.get(0) == list.get(1)){
                return true;
            }else{
                return false;
            }
        }
        boolean flag;
        for(int start = list.size()-1; start > 1; start--){
            //找刻子
            if(list.get(start) == list.get(start-1) && list.get(start-1) == list.get(start-2)){
                Integer a = list.get(start);
                list.remove(a);
                list.remove(a);
                list.remove(a);
                flag = fun(list);
                if(flag){
                   return true;
                }else{
                    list.add(start-2, a);
                    list.add(start-2, a);
                    list.add(start-2, a);
                    break;
                }
            }
        }
        int temp = list.size()-1;
        for(int start = temp; start > 1; start--){
            //找顺子
            if(list.get(start)-1 == list.get(start-1)){
                //找到第一个不相同的点
                int i = start-2;
                while(i>=0){
                    if(list.get(start-1)-1 == list.get(i)){
                        Integer a = list.get(start);
                        Integer b = list.get(start-1);
                        Integer c = list.get(i);
                        list.remove(a);
                        list.remove(b);
                        list.remove(c);
                        flag = fun(list);
                        if(!flag){
                            list.add(i, c);
                            list.add(start-1, a);
                            list.add(start-1, b);
                            start = temp--;
                            break;
                        }else{
                            return true;
                        }
                    }
                    i--;
                }
            }
        }
        return false;
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

华为笔试算法:清一色胡牌问题(java) 的相关文章

  • 【AI视野·今日Robot 机器人论文速览 第九期】Thu, 17 Jun 2021

    AI视野 今日CS Robotics 机器人学论文速览 Thu 17 Jun 2021 Totally 15 papers x1f449 上期速览 更多精彩请移步主页 Daily Robotics Papers Autonomous Nav
  • SpringBoot 集成cas5.3 实现sso单点登录

    博主说明 这篇文章速成cas xff0c 下面包含了cas统一认证登录 xff0c 统一认证登出 有兴趣想了解更多cas内容的可以看看我下面这些文章 springboot 使用cas5 3 sso概念springboot 集成cas5 3
  • UltraVNC 使用,内网局域网远程控制

    介绍 UltraVNC 是客户端 服务器软件 xff0c 允许你经由 TCP IP 连线 xff08 也就是主机都在同一网络环境下 xff09 xff0c 控制远端的电脑 这个版本的开发以 RealVNC 为基础 xff0c 加上了Tigh
  • JS判断一个字符串是否在数组中

    方法1 xff1a arr indexOf 某元素 xff1a 未找到则返回 1 span class token keyword var span number span class token operator 61 span span
  • pb9 数据窗口的计算列

    数据窗口中 xff0c 可以增加计算列 xff0c 进行合计 平均或者其他计算动作 在窗口的按钮 xff0c 或者其他事件中 xff0c 可以对数据窗口的计算列的表达式进行修改 xff0c 这样可以将数据窗口多用 办法 xff1a dw 1
  • tar打包命令(linux)

    1 打包命令 span class token function tar span cvf 归档路径 被打包文件路径 span class token punctuation span c create archive v verbose
  • Python字符串与数组相互转换

    Python中有join 和os path join 两个函数 xff0c 具体作用如下 xff1a join xff1a 连接字符串数组 将字符串 元组 列表中的元素以指定的字符 分隔符 连接生成一个新的字符串os path join x
  • FastApi 文件上传upload

    需要使用的Python包 xff1a fastapi和uvicorn span class token keyword import span time span class token keyword import span uvicor
  • zip/tar 分割压缩和合并解压

    1 zip 分割压缩和合并解压 span class token comment 准备工作 xff1a 将文件或文件夹打包为zip压缩包 span span class token function zip span r src zip s
  • python 创建excel 并保存(两种方法)

    1 概要 python中的包xlwt和xlsxwriter都是比较方便创建excel文件并写入数据的 2 xlwt 创建excel并保存 xlwt中 xff1a 通过xlwt Workbook 来新建工作簿 xff1b 通过 add she
  • Python 保留两位小数几种方法

    一 xff1a 保留两位小数 且 做四舍五入处理 四舍六入五成双 xff0c 四舍六入五凑偶的意思 xff0c 根据百度词条的解释如下 xff08 1 xff09 当精确位后面一位的数字是1 4的时候 xff0c 舍去 xff08 2 xf
  • XSS 攻击常用代码

    1 XSS 攻击常用代码 span class token number 1 span 39 34 span class token punctuation span span class token punctuation span sp
  • xpath 爬虫案例

    1 案例 爬取糗百中的段子内容和作者名称 span class token keyword from span lxml span class token keyword import span etree url span class t
  • Selenium 鼠标滚动操作

    1 JS处理滚动条问题 span class token number 1 span 滚动条回到顶部 xff1a js span class token operator 61 span span class token string 34
  • selenium 定位元素(并集)

    并集 xff1a answer 61 driver find element By CLASS NAME info content and huida con text 1 id 说明 xff1a 通过元素的id属性来定位元素 xff0c
  • 精细粒度访问控制:DBMS_RLS包实现数据库表行级安全控制

    精细粒度访问控制 xff1a DBMS RLS包实现数据库表行级安全控制 这是行级控制 xff0c 并且用的数据库提供的dbms包做的 xff0c 而不是视图或者触发器 xff0c 据说 xff0c 可以对所有的DML起作用 精细粒度访问控
  • java获取json数组格式中的值

    第一种方法 xff1a String str span class token operator 61 span span class token string 34 39 array 39 39 id 39 5 39 name 39 39
  • 程序员面试经历

    现在找工作 已经没有了毕业以后那时候找工作的那种紧张心情 自从在上家公司离职以后 自己进行了一段时间的工作 世界上本来没有面霸 面试的多了 也就成了面霸 不得不承认 一开始自己面试是有些紧张 但是 面试的多了 也就不觉得紧张 反而有些平淡了
  • 宽度优先爬虫和带偏好的爬虫

    互联网可以看成一个超级大的 图 xff0c 而每个页面可以看成一个 节点 页面中的链接可以看成是图的 有向边 因此 xff0c 能够通过图的遍历得方式对互联网这个超级大 图 进行访问 图的遍历可以分为宽度优先遍历和深度优先遍历 xff0c
  • The connection to the server localhost:8080 was refused

    最近在学习安装Kubernetes集群的时候 xff0c 安装完执行sudo kubectl get nodes命令出现这个报错 xff1a 下面是解决方法 Master节点出现这个报错 首先需要检查Master安装完Kubernetes后

随机推荐