题解 | #24点运算#

24点运算

http://www.nowcoder.com/practice/7e124483271e4c979a82eb2956544f9d

  • 实际上是允许有括号的
  • 先将输入的字母转换成待处理的数字
  • 要通过input得到sum。即:遍历每个input元素(正负不能改变),加减乘除剩下的元素,递归判断能否得到对应的sum加减乘除。注意除的时候,余数必须为0
  • 计算完成后,将处理的数字转换成字母,注意开头的+号是不需要的
import java.util.Scanner;

/**
 * class com.sloera.nowcoder
 * user sloera
 * date 2022/2/27
 */
public class Main {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    // 注意 hasNext 和 hasNextLine 的区别
    while (in.hasNextLine()) { // 注意 while 处理多个 case
      final String s = in.nextLine();
      String result = resolve(s);
      System.out.println(result);
    }
  }

  private static String resolve(String s) {
    // 3.输入4张牌为字符串形式,以一个空格隔开,首尾无空格;如果输入的4张牌中包含大小王,则输出字符串“ERROR”,表示无法运算;
    if (s.contains("joker") || s.contains("JOKER")) {
      return "ERROR";
    }
    final String[] split = s.split("\\s+");
    int[] input = new int[split.length];
    // 得到输入的数字
    // 2.牌面2~10对应的权值为2~10, J、Q、K、A权值分别为为11、12、13、1;
    for (int i = 0; i < split.length; i++) {
      switch (split[i]) {
        case "J": input[i] = 11; break;
        case "Q": input[i] = 12; break;
        case "K": input[i] = 13; break;
        case "A": input[i] = 1; break;
        default:
          input[i] = Integer.parseInt(split[i]);
      }
    }
    // 计算是否能得到24点
    final char[] operators = new char[4];
    final int[] number = new int[4];
    boolean flag = canculate(operators, number, input, 24);
    if (flag) {
      final StringBuilder stringBuilder = new StringBuilder();
      for (int i = number.length-1; i >= 0; i--) {
        if (i != number.length - 1 || operators[i] != '+') {
          stringBuilder.append(operators[i]);
        }
        if (number[i] == 1) {
          stringBuilder.append('A');
        } else if (number[i] == 11) {
          stringBuilder.append('J');
        }else if (number[i] == 12) {
          stringBuilder.append('Q');
        }else if (number[i] == 13) {
          stringBuilder.append('K');
        } else {
          stringBuilder.append(number[i]);
        }
      }
      return stringBuilder.toString();
    }
    return "NONE";
  }

  /**
   * 是否能由 input 中的数字,计算出sum
   *
   * @param operators 操作符记录
   * @param number 数字计算顺序
   * @param input 可选数字
   * @param sum 总数
   * @return boolean
   * @date 2022/2/27
   */
  private static boolean canculate(char[] operators, int[] number, int[] input, int sum) {
    if (input.length == 1) {
      if (input[0] == sum) {
        operators[3] = '+';
        number[3] = sum;
        return true;
      }
    }
    for (int i = 0; i < input.length; i++) {
      int[] newInput = getNewInput(input, i);
      //  ? = sum + input[i]
      if (canculate(operators, number, newInput, sum + input[i])) {
        // 这里记录的是input[i], ? 已经在递归里面记录了
        operators[operators.length - newInput.length - 1] = '-';
        // 这里记录的是input[i], ? 已经在递归里面记录了
        number[number.length - newInput.length - 1] = input[i];
        return true;
      }
      //  ? = sum - input[i]
      if (canculate(operators, number, newInput, sum - input[i])) {
        // 这里记录的是input[i], ? 已经在递归里面记录了
        operators[operators.length - newInput.length - 1] = '+';
        // 这里记录的是input[i], ? 已经在递归里面记录了
        number[number.length - newInput.length - 1] = input[i];
        return true;
      }
      //  ? = sum * input[i]
      if (canculate(operators, number, newInput, sum * input[i])) {
        // 这里记录的是input[i], ? 已经在递归里面记录了
        operators[operators.length - newInput.length - 1] = '/';
        // 这里记录的是input[i], ? 已经在递归里面记录了
        number[number.length - newInput.length - 1] = input[i];
        return true;
      }
      //  ? = sum / input[i]
      if (canculate(operators, number, newInput, sum / input[i])  && (sum % input[i] == 0)) {
        // 这里记录的是input[i], ? 已经在递归里面记录了
        operators[operators.length - newInput.length - 1] = '*';
        // 这里记录的是input[i], ? 已经在递归里面记录了
        number[number.length - newInput.length - 1] = input[i];
        return true;
      }
    }
    return false;
  }

  /**
   * 获取input中,除index索引所在位置的新数组
   *
   * @param input 原始数组
   * @param index 待去除索引
   * @return int[]
   * @date 2022/2/27
   */
  private static int[] getNewInput(int[] input, int index) {
    final int[] ints = new int[input.length - 1];
    int j = 0;
    for (int i = 0; i < input.length; i++) {
      if (i != index) {
        ints[j++] = input[i];
      }
    }
    return ints;
  }
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
昨天 14:00
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 18:05
点赞 评论 收藏
分享
下个早班:秒挂就是不缺人
点赞 评论 收藏
分享
05-11 11:48
河南大学 Java
程序员牛肉:我是26届的双非。目前有两段实习经历,大三上去的美团,现在来字节了,做的是国际电商的营销业务。希望我的经历对你有用。 1.好好做你的CSDN,最好是直接转微信公众号。因为这本质上是一个很好的展示自己技术热情的证据。我当时也是烂大街项目(网盘+鱼皮的一个项目)+零实习去面试美团,但是当时我的CSDN阅读量超百万,微信公众号阅读量40万。面试的时候面试官就告诉我说觉得我对技术挺有激情的。可以看看我主页的美团面试面经。 因此花点时间好好做这个知识分享,最好是单拉出来搞一个板块。各大公司都极其看中知识落地的能力。 可以看看我的简历对于博客的描述。这个帖子里面有:https://www.nowcoder.com/discuss/745348200596324352?sourceSSR=users 2.实习经历有一些东西删除了,目前看来你的产出其实很少。有些内容其实很扯淡,最好不要保留。有一些点你可能觉得很牛逼,但是面试官眼里是减分的。 你还能负责数据库表的设计?这个公司得垃圾成啥样子,才能让一个实习生介入数据库表的设计,不要写这种东西。 一个公司的财务审批系统应该是很稳定的吧?为什么你去了才有RBAC权限设计?那这个公司之前是怎么处理权限分离的?这些东西看着都有点扯淡了。 还有就是使用Redis实现轻量级的消息队列?那为什么这一块不使用专业的MQ呢?为什么要使用redis,这些一定要清楚, 就目前看来,其实你的这个实习技术还不错。不要太焦虑。就是有一些内容有点虚了。可以考虑从PR中再投一点产出
投递美团等公司8个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务