目录
题目描述
思路解析
根据题目意思,我们可以得知如果卡牌正反面数字一样,那么该数字绝对不可能成为答案。换一种表述就是答案只可能在正反面不同的卡牌中诞生。
因为计算机的离散化处理方式,且具体到题目,本道题是最优化过程。所以我们可以尝试使用动态规划的思路。即寻找最优子结构来解题。
基于以上阐述,我们先不妨规定 表示前 i 张卡片的最小背面值。当我们加入第 i + 1 张卡片时,我们不妨先观察会产生几种结果,并分析产生条件。分析如下:
结果1:。 条件:
为最小的卡面 / i + 1的卡面在前 i 张牌的正面值都出现过
结果2: = 第 i + 1 张卡片的正面值。 条件:第 i + 1 张正面值在此前正面未出现且最小
结果3: = 第 i + 1 张卡片的反面值。 条件:第 i + 1 张反面值在此前正面未出现且最小
我们可以看到对于上面三个结果以及条件中,我们其实只需要对结果2进行翻转操作。因为对于其他结果翻转是不需要的/无用的。
并且有一个显而易见的事实就是可能为答案的较小值都在卡牌背面。基于这个事实,我们可以分析出,如果第 i + 1 张无论是正反面的值要是在此前出现过,那么它一定比 大,即不可能成为答案。如果它比
小,那么它在次之前不可能出现。
基于这个分析,我们就可以免除记录前面牌面的状态记录
AC代码
class Solution {
public:
int flipgame(vector<int>& fronts, vector<int>& backs) {
unordered_set<int> s;
int n = fronts.size();
int ans = 3000; //设计足够大
for (int i = 0; i < n; ++i) {//标记不可能为答案的值
if (fronts[i] == backs[i]) {
s.insert(fronts[i]);
}
}
for (int i = 0; i < n; ++i) {//开始规划
int flag_front = s.count(fronts[i]);
int flag_back = s.count(backs[i]);
if (flag_back * flag_front) {//前后的值都不可能为答案则执行下一个卡片
continue;
}
if (flag_back == 0) {
ans = min(ans, backs[i]);
}
if (flag_front == 0) {
ans = min(ans, fronts[i]);
}
}
return ans % 3000;//等价于 ans == 3000? 0: ans;
}
};