算法设计与分析第四周作业——24Game
这周讲了深度优先搜索算法和广度优先搜索算法,所以找了一道深度优先搜索有关的题目进行作业。
本周所选题目:原题目链接
题目详情
题目大意:给出四个数字,进行加、减、乘、除运算,使得最后得到的结果为24,其中要注意的是除法时是精准的,比如1除以3可以理解为得到分数1/3。
输入:还有四个从1到9的正整数的数组。
输出:判断是否能经过运算得到24,是则返回true,否则返回false。
举例说明:
Input: [4, 1, 8, 7]
Output: True
Explanation: (8-4) * (7-1) = 24
Input: [1, 2, 1, 2]
Output: False
题目分析和算法设计
这个题目像小时候玩的卡牌游戏,四个人每人抽出一张卡牌,谁能够最快地使用加减乘除运算得到24则为赢家。其中每张牌只能使用一次,即经过运算后,使用过的卡牌将无效,运算得到的中间数字再与剩下未使用过的卡牌进行运算,知道得到24为止。
比如上述的卡牌【4,1,8,7】的计算过程为:
- 8 - 4得到4,卡牌变为(想象):【4,1,7】;
- 7 - 1得到6,卡牌变为:【4,6】;
- 4 * 6得到24,说明该组卡牌能够通过运算得到24。
当然,上述是人为的进行运算,对于计算机来说,需要通过遍历进行计算并比较,过程是复杂很多的,其实可以想象得到,这是一个深度优先搜索的问题,对于每个数字(不管是原数字还是中间数字),都与别的数字进行运算,直到得到24为止。
那么,可以使用一个卡牌数组来模拟场景的实现,对于每一种运算情况都使用递归,其中递归函数的出口为卡牌数组还剩一个数且该数为24。对于卡牌数组中,使用过的卡牌将被“废弃”,并使用运算得到的结果作为新的卡牌填充入卡牌数组中。
代码详情
class Solution {
private:
bool isValid;
public:
bool judgePoint24(vector<int>& nums) {
isValid = false;
vector<double> cards(nums.begin(), nums.end());
judgeIsValid(cards);
return isValid;
}
void judgeIsValid(vector<double> &cards) {
// 当还剩下一个数字并且数字为24时,即可注意到维浮点数,不能直接判断等于
if (isValid) return;
if (cards.size() == 1 && abs(cards[0] - 24) < 0.001) isValid = true;
int size = cards.size();
for (int i = 0; i < size; i ++) {
for (int j = 0; j < size; j ++) {
// 同一个数字不能考虑两次
if (i == j) continue;
vector<double> tmpCards = cards;
double num1 = tmpCards[i];
double num2 = tmpCards[j];
// 去掉用过的数字,加入经过运算得到的新的数字
// 可以理解为删掉下标大的数字,把下标小的数字替换为新的数字
int maxIndex = i > j ? i : j;
int minIndex = i > j ? j : i;
tmpCards.erase(tmpCards.begin() + maxIndex);
// 对每一个运算过程递归调用
tmpCards[minIndex] = num1 + num2;
judgeIsValid(tmpCards);
tmpCards[minIndex] = num1 - num2;
judgeIsValid(tmpCards);
tmpCards[minIndex] = num1 * num2;
judgeIsValid(tmpCards);
if (num2 != 0) {
tmpCards[minIndex] = num1 / num2;
judgeIsValid(tmpCards);
}
}
}
}
};
需要注意的是因为运算得到的数是浮点数,不能直接进行等价比较,所以只要得到的结果与24相差不超过0.001,即可判断该结果为24。
思考与总结
该题目主要的难点在于是根据题目构建模型和如何实现递归函数进行求解,本来设计是队规函数返回类型为bool值,只用递归函数返回的结果作为最终输出,递归函数的出口也是卡牌数组还剩一个数且该数为24,但是这样做的话只能判断某一些能够得到24的数组,至于其他的情况并没有返回值进行判断,所以会出现错误。因此使用一个全局bool变量来作为最终输出结果。
参考资料:
- http://www.cnblogs.com/grandyang/p/8395062.html
- https://blog.csdn.net/gangtaolun8493/article/details/78063690
谢谢阅读。