LeetCode week 3 : 24 Game

来源:互联网 发布:c语言乘法函数是什么 编辑:程序博客网 时间:2024/06/07 16:10

题目

地址: https://leetcode.com/problems/24-game/description/
类别: Deep-first Search
难度: Hard
描述:
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的整数的卡片(允许重复数字),需要判断是否能通过对这四个数字进行+, -,*, /以及()这5种运算得到24。注意”-“只能为二元操作符,而且除法不是整除,而是精确除。
我们从例子出发:
Input: [4, 1, 8, 7]
Output: True
Explanation: (8-4) * (7-1) = 24
分解:

操作 操作后更新集合 8 - 4 = 4 4, 7, 1 7 - 1 = 6 4, 6 4 * 6 = 24 24

由上面的例子我们可以得到启发:我们每进行一次操作,当集合中数字个数大于等于2时,我们都是取出其中两个进行一次操作并将操作得到的结果放入集合,将两个操作数丢弃,然后对更新后的集合进行检验;而当最后集合中只剩下1个数时,我们只需比较它是否与24相等,若与24相等则返回成功且不需再遍历;若与24不相等则需要继续遍历剩下的可能情况直到找到成功示例,或遍历完而未找到返回失败为止。
实现的难点主要在于不重不漏地遍历所有的组合,对此我们可以基于深度优先遍历实现。
下图为深搜树的一小部分:
每次分裂节点依据为:所有两个不同操作数的排列组合及操作符的选取。
比如[4, 1, 8, 7]集合
不同操作数的排列组合:A(4, 2) = 12
不同操作符:4
分裂节点共:12*4 = 8 种
最后时间复杂度为O(12*4*6*4*2*4)为O(1)
这里写图片描述

代码实现

class Solution {private:    bool flag;public:    bool judgePoint24(vector<int>& nums) {        vector<double> cards;        flag = false;        for(int i=0; i<nums.size(); i++) cards.push_back(nums[i]);        valid(cards);        return flag;    }    void valid(vector<double> & cards) {        if(flag) return;        else if(cards.size() == 1) {            flag = (abs(cards[0] - 24.0) < 0.001);        }        else {            for(int i = 0; i < cards.size(); i++) {                for(int j = 0; j < cards.size(); j++) {                    if(i == j) continue;                    vector<double> subCards = cards;                    double operand0 = subCards[i];                    double operand1 = subCards[j];                    subCards.erase(subCards.begin() + (i<j ? j:i));                    int p = min(i, j);                    subCards[p] = operand0 + operand1;                    valid(subCards);                    subCards[p] = operand0 - operand1;                    valid(subCards);                    subCards[p] = operand0 * operand1;                    valid(subCards);                    if(operand1 != 0) {                        subCards[p] = operand0 / operand1;                        valid(subCards);                    }                }            }        }    }};

在看讨论区的时候还看到了一个比较有意思的解法:
解法地址

class Solution:    def judgePoint24(self, nums):        """        :type nums: List[int]        :rtype: bool        """        bad = '对撒剘劥圞剜劏哱掶桺泛揋掵従剟剣彫寣污悫壛梄甏咍哲汭剤堧点卋嬞勆叛汬泐塵栋劚嚮咃宠吖剗楗囧力桻攋壯劯嗏桹劙剢剚焧啫栕炸栫栖嚲彳剛撑烃洿宋汷彲剙揁妷埻撧汢吩壙劇剭埼吕剝汣敯憇勇剥咎囻匓'        return chr(int(''.join(map(str, sorted(nums)))) + 19968) not in bad

这种解法的思想是:既然4张卡片数字的排列组合是有限的,那么我们可以直接判断给出数字集合是否属于正确集合(当然前提是得到那些正确或者错误的集合)。

参考地址

https://discuss.leetcode.com/topic/104169/c-straight-forward-backtracking-solution
https://discuss.leetcode.com/topic/103979/%EB%96%A2%EB%B8%BB%EA%B0%81%EA%B1%8E%EB%83%87%EA%B0%85%EA%B0%B8%EA%BA%9A%EB%B5%9F%EC%88%A3%EC%9A%84%EB%B5%B4%EB%B5%9E%EB%A4%BC%EA%B0%88%EA%B0%8C%EB%A4%94%EB%96%8C%EC%98%8A%EB%A9%94%EB%8A%84%EC%88%AD%EC%BA%B8%EA%B8%B6%EA%BA%9B%EC%98%96%EA%B0%8D%EB%87%90%EC%A9%A2%EA%B3%B4%EB%93%87%EA%B1%AF%EA%B6%84%EC%98%95%EC%99%B9%EB%88%9E%EC%86%B4%EA%B1%83%EB%81%97%EA%B8%AC%EB%95%89%EA%B6%BF%EA%B0%80%EC%8C%80%EB%82%90%EA%B1%84%EC%88%A4%EB%BA%B4%EB%8A%98%EA%B1%98%EA%BD%B8%EC%88%A2%EA%B1%82%EA%B0%8B%EA%B0%83%EC%AB%90%EA%BC%94%EC%86%BE%EC%A9%A1%EC%87%94%EC%86%BF%EB%81%9B%EB%A4%9C%EA%B0%84%EB%B8%BA%EC%A9%AC%EC%9B%A8%EB%94%B4%EC%98%A0%EB%A4%9B%EA%B0%82%EB%B5%AA%EB%8D%A0%EB%86%A4%EB%B9%90%EC%98%8B%EA%B7%92%EB%8A%82%EA%B0%B0%EA%B0%96%EB%86%A5%EA%B6%BE%EA%B0%86%EC%98%8C%EB%BC%98%EB%AC%B0%EA%B1%B0%EA%B0%8E%EA%B8%B7%EB%82%A4%EA%B2%BC/8

原创粉丝点击