679-24 Game

Description:
You have 4 cards each containing a number from 1 to 9. You need to judge whether they could operated through *, /, +, -, (, ) to get the value of 24.

Example 1:
Input: [4, 1, 8, 7]
Output: True
Explanation: (8-4) * (7-1) = 24

Example 2:
Input: [1, 2, 1, 2]
Output: False

Note:
1.The division operator / represents real division, not integer division. For example, 4 / (1 - 2/3) = 12.
2.Every operation done is between two numbers. In particular, we cannot use - as a unary operator. For example, with [1, 1, 1, 1] as input, the expression -1 - 1 - 1 - 1 is not allowed.
3.You cannot concatenate numbers together. For example, if the input is [1, 2, 1, 2], we cannot write this as 12 + 12.

问题描述:
输入为一个数组,其中包含4个元素,范围都在[1,9]中,你需要对这四个元素进行四则运算,判断能否得到24.

例子:
输入:[4, 1, 8, 7]
输出:True
解释:(8 - 4) * (7 - 1) = 24

解法1(回溯法):

/*
模拟所有的可能性,一一确认是否可以得到24
*/
class Solution {
    public boolean judgePoint24(int[] nums) {
        List line = new ArrayList();
        for(int i : nums)   line.add((double)i);

        return solve(line);
    }
    public boolean solve(List line){
        if(line.size() == 0)    return false;
        if(line.size() == 1)    return Math.abs(line.get(0) - 24) < 1e-6;

        int size = line.size();
        for(int i = 0;i < size;i++){
            for(int j = 0;j < size;j++){
                if(i == j)  continue;
                List newLine = new ArrayList();
                for(int k = 0;k < size;k++){
                    if(k != i && k != j)    newLine.add(line.get(k));
                }

                for(int k = 0;k < 4;k++){
                    //注意这里,因为+号和*号不会因为两个数换个位置就变结果
                    if(k < 2 && i > j)  continue;
                    double num = 0;
                    if(k == 0)  num = line.get(i) + line.get(j);
                    if(k == 1)  num = line.get(i) * line.get(j);
                    if(k == 2)  num = line.get(i) - line.get(j);
                    if(k == 3){
                        //注意这里,/不允许除数为0
                        if(line.get(j) == 0)    continue;
                        num = line.get(i) / line.get(j);
                    }
                    newLine.add(num);
                    if(solve(newLine))  return true;
                    newLine.remove(newLine.size() - 1);
                }
            }
        }

        return false;
    }
}

解法2(回溯法):

class Solution {
    final double eps = 0.001;
    public boolean judgePoint24(int[] nums) {
        return f(new double[] {nums[0], nums[1], nums[2], nums[3]});
    }

    private boolean f(double[] a) {
        if (a.length == 1) {
            if(Math.abs(a[0] - 24.0) < eps)
               return true;

        }
        for (int i = 0; i < a.length; i++) {
            //注意这里,与解法1不同,因为在compute里面已经包含了两个数的前后顺序
            for (int j = i + 1; j < a.length; j++) {
                double[] b = new double[a.length - 1];
                for (int k = 0, l = 0; k < a.length; k++) {
                    if (k != i && k != j) {
                        b[l++] = a[k];
                    }
                }
                for (double k : compute(a[i], a[j])) {
                    b[a.length - 2] = k;
                    if (f(b)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    //这里很好,把取数逻辑分离开了
    private double[] compute(double a, double b) {
        return new double[] {a + b, a - b, b - a, a * b, a / b, b / a};
    }
}

你可能感兴趣的:(算法与数据结构,leetcode全解)