leetcode--882.反转卡片游戏

目录

题目描述

思路解析

AC代码


题目描述

822.反转卡片游戏

 

思路解析

根据题目意思,我们可以得知如果卡牌正反面数字一样,那么该数字绝对不可能成为答案。换一种表述就是答案只可能在正反面不同的卡牌中诞生

因为计算机的离散化处理方式,且具体到题目,本道题是最优化过程。所以我们可以尝试使用动态规划的思路。即寻找最优子结构来解题。

基于以上阐述,我们先不妨规定  S_{i} 表示前 i 张卡片的最小背面值。当我们加入第 i + 1 张卡片时,我们不妨先观察会产生几种结果,并分析产生条件。分析如下:

结果1:S_{i + 1} = S_{i}。 条件:S_{i} 为最小的卡面 / i + 1的卡面在前 i 张牌的正面值都出现过

结果2:S_{i + 1} = 第 i + 1 张卡片的正面值。 条件:第 i + 1 张正面值在此前正面未出现且最小

结果3:S_{i + 1} = 第 i + 1 张卡片的反面值。 条件:第 i + 1 张反面值在此前正面未出现且最小

我们可以看到对于上面三个结果以及条件中,我们其实只需要对结果2进行翻转操作。因为对于其他结果翻转是不需要的/无用的。

并且有一个显而易见的事实就是可能为答案的较小值都在卡牌背面。基于这个事实,我们可以分析出,如果第 i + 1 张无论是正反面的值要是在此前出现过,那么它一定比 S_{i} 大,不可能成为答案。如果它比 S_{i} 小,那么它在次之前不可能出现。

基于这个分析,我们就可以免除记录前面牌面的状态记录

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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值