zoukankan      html  css  js  c++  java
  • [leetCode]679. 24 点游戏

    在这里插入图片描述

    回溯法

    一共4个数字4种运算,可以通过回溯法遍历不同的可能性。

    • 从4个数字中取出两个数字,并选择一种运算有 4*3=12种,将运算结果取代取出的两个数字等到3个数字
    • 在剩下三个数字种取出两个数字并选择一种运算有 3*2 = 6种, 将运算结果取代取出的两个数字还剩2数字
    • 剩下两个数字有两种不同的顺序,可选择一种运算
      因此,一共有:124+64+2*4=9216种可能性。

    回溯的具体做法是,使用一个列表存储目前的全部数字,每次从列表中选出 2 个数字,再选择一种运算操作,用计算得到的结果取代选出的 2 个数字,这样列表中的数字就减少了 1 个。重复上述步骤,直到列表中只剩下 1个数字,这个数字就是一种可能性的结果,如果结果等于 24,则说明可以通过运算得到 24。如果所有的可能性的结果都不等于 24,则说明无法通过运算得到 24
    注意点:

    • 需要注意浮点运算的精度与除数为0的情况
    • 由于加法与乘法符合交换律因此可以进行优化,跳过一种顺序
    class Solution {
        // 目标值
        static final int TARGET = 24;
        // 浮点运算允许的误差
        static final double EPSILON = 1e-6;
        // 加减乘除
        static final int ADD = 0, MULTIPLY = 1, SUBTRACT = 2, DIVIDE = 3;
    
        public boolean judgePoint24(int[] nums) {
            // 将四个数字加入链表
            List<Double> list = new ArrayList<>();
            for (int num : nums) 
                list.add((double)num);
            return solve(list);
        }
    
        private boolean solve(List<Double> list) {
            if (list.size() == 0) return false;
            if (list.size() == 1)
                return Math.abs(list.get(0) - TARGET) < EPSILON;
            int size = list.size();
            // i,j为取出两个数字的下标
            for (int i = 0; i < size; i++) 
                for (int j = 0; j < size; j++) {
                    if (i != j) {
                        List<Double> list2 = new ArrayList<>();
                        // 添加 i, j以外的另外两个数字
                        for (int k = 0; k < size; k++) {
                            if (k != i && k != j) {
                                list2.add(list.get(k));
                            }
                        }
                        for (int k = 0; k < 4; k++) {
                            // 加法和乘法符合交换律,对于取出的两个数字其中一种顺序不用考虑
                            if (k < 2 && i > j)
                                continue;
                            if (k == ADD) {
                                list2.add(list.get(i) + list.get(j));
                            } else if (k == MULTIPLY) {
                                list2.add(list.get(i) * list.get(j));
                            } else if (k == SUBTRACT) {
                                list2.add(list.get(i) - list.get(j));
                            }else if (k == DIVIDE) {
                                if (Math.abs(list.get(j)) < EPSILON)
                                    continue;
                                else 
                                    list2.add(list.get(i) / list.get(j));
                            }
                            if (solve(list2))
                                return true;
                            list2.remove(list2.size() - 1);
                        }
                    }
                }
            return false;
        }
    }
    
  • 相关阅读:
    TabActivity 、fragemnt+fragment 和 Fragment+Viewpager 优缺点
    Android App的签名打包(晋级篇)
    Android ProgressBar 进度条荧光效果
    Android UI【android 仿微信、QQ聊天,带表情,可翻页,带翻页拖动缓冲】
    Android UI--自定义ListView(实现下拉刷新+加载更多)
    Android平台下利用zxing实现二维码开发
    自定义组件---图片和文字实现ImageButton效果
    JNI由浅入深_10_JNI 综合开发
    开关按钮实现
    Android Asynctask与Handler的比较,优缺点区别,Asynctask源码
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13859889.html
Copyright © 2011-2022 走看看