679. 24 Game

679. 24 Game


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.

题目大意

给定一个由四个整数组成的序列,判断其能否通过加、减、乘、除,最终得到24
注意:
1. 可以进行小数运算
2. 不可以将-当作一元操作符。
3. 不可以将数字进行合并。

解题思路

使用DFS的思路,穷举所有的可能,一旦发现满足的答案,则返回正确;当穷举完所有可能,仍不存在解,则说明这组序列不存在计算可以获得24.
每次将两个数字的计算结果保存在其中一个数字的位置上,同时,将另一个数字的位置设为已被访问,不允许再次访问。再将这个计算结果和当前使用过的数字总数递归调用函数自身。每组数对,分别执行加减乘除四个操作,当得到24时,立即结束返回结果;如果没有得到24时,将刚刚被赋值的位置还原会原来的值,并且取出另一个位置被访问的标识(这一步极为重要,保证在回溯时,还原之前的操作)。
使用cur变量确定当前已经访问到底几个数字,当访问到第4个数字时,在数组中寻找是否存在没被访问,且等于24的节点,如果存在,则说明这四个数字可以计算得到24

细节:
1. 因为使用的是浮点数,所以难免存在精度误差,为了避免精度误差,所以将 abs(x) < 1e-4等同于x == 0.
2. 零不可以作为除数。
3. 使用vis记录当前节点是否已经被访问过。

代码实现

class Solution {
public:
    const double EPS = 1e-4;
    bool dfs(vector<double>& nums, deque<bool>& vis, int cur) {
        if (cur == 4) {
            for (int i = 0; i < 4; i++) {
                if (!vis[i] && abs(nums[i]-24.0) < EPS) { return true; }
            }
            return false;
        }
        for (int i = 0; i < 4; i++) {
            if (vis[i]) continue;
            for (int j = i+1; j < 4; j++) {
                if (vis[j]) continue;
                vis[j] = true;
                double x = nums[i];
                double y = nums[j];
                // +
                nums[i] = x+y;
                if (dfs(nums, vis, cur+1)) { return true; }
                // *
                nums[i] = x*y;
                if (dfs(nums, vis, cur+1)) { return true; }
                // -
                nums[i] = x-y;
                if (dfs(nums, vis, cur+1)) { return true; }
                nums[i] = y-x;
                if (dfs(nums, vis, cur+1)) { return true; }
                // /
                if (abs(y) > EPS) {
                    nums[i] = x / y;
                    if (dfs(nums, vis, cur+1)) { return true; }
                }
                if (abs(x) > EPS) {
                    nums[i] = y / x;
                    if (dfs(nums, vis, cur+1)) { return true; }
                }

                /** important step **/
                nums[i] = x;
                vis[j] = false;
            }
        }
        return false;
    }
    bool judgePoint24(vector<int>& nums) {
        vector<double> doubleNums(4, 0.0);deque<bool> vis(4, false);
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            doubleNums[i] = nums[i];
        }
        return dfs(doubleNums, vis, 1);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值