Two-Letter Card Game

Two-Letter Card Game

You are given a deck of cards represented by a string array cards, and each card displays two lowercase letters.

You are also given a letter x. You play a game with the following rules:

  • Start with 0 points.
  • On each turn, you must find two compatible cards from the deck that both contain the letter x in any position.
  • Remove the pair of cards and earn 1 point.
  • The game ends when you can no longer find a pair of compatible cards.

Return the maximum number of points you can gain with optimal play.

Two cards are compatible if the strings differ in exactly 1 position.

 

Example 1:

Input: cards = ["aa","ab","ba","ac"], x = "a"

Output: 2

Explanation:

  • On the first turn, select and remove cards "ab" and "ac", which are compatible because they differ at only index 1.
  • On the second turn, select and remove cards "aa" and "ba", which are compatible because they differ at only index 0.

Because there are no more compatible pairs, the total score is 2.

Example 2:

Input: cards = ["aa","ab","ba"], x = "a"

Output: 1

Explanation:

  • On the first turn, select and remove cards "aa" and "ba".

Because there are no more compatible pairs, the total score is 1.

Example 3:

Input: cards = ["aa","ab","ba","ac"], x = "b"

Output: 0

Explanation:

The only cards that contain the character 'b' are "ab" and "ba". However, they differ in both indices, so they are not compatible. Thus, the output is 0.

 

Constraints:

  • 2 <= cards.length <= 105
  • cards[i].length == 2
  • Each cards[i] is composed of only lowercase English letters between 'a' and 'j'.
  • x is a lowercase English letter between 'a' and 'j'.

 

解题思路

  这周末打的 atc 和两场 lc 都莫名其妙爆 0 了,不知道为什么做题一点思路都没有。也许是因为最近心情不好导致整个人变傻了,不过最近不愉快的事情确实有点多就是了。一眨眼都 9 月,时间过得真快啊。

  这题的做法也是经典中的经典了,不过最逆天的是每次我遇到这类题都想不到这个结论。比如 A. Cards Partition小L的位运算,甚至是上周的题 Partition Array Into K-Distinct Groups。这些问题抽象出来都是,给定 $n$ 个元素,每次从中选出 $m$ 个互不相同的元素,问是否能将所有元素选完。对应的结论为,首先需要满足 $m \mid n$。其次,如果某个元素的出现次数最大,并且该次数大于 $\tfrac{n}{m}$,则无解;否则有解。

  回到这题,由于每张牌必须包含字符 $x$,意味着符合要求的牌要么是 $i \, x$ 的形式,要么是 $x \, i$ 的形式,其中 $i \in \{ \text{'a'},\text{'b'},\ldots,\text{'j'} \}$。同时,由于只有在恰好一个位置上的字符相同的两张牌才兼容,因此每次要么在 $i \, x$ 或 $x \, i$ 同一形式的牌中选择两张 $i$ 不同的牌,要么一张在 $i \, x$ 形式的牌中选(且 $i \ne x$)另一张在 $x \, i$ 形式的牌中选 $x \, x$(同理 $x \, i$ 的情况)。

  为了简单假设我们现在不考虑 $x \, x$ 的牌,此时问题就被限定为只能从同一形式的牌中选择两张不同的牌。这就是上面提到的经典结论了,不过本题要求的是最多能选多少次,而不是是否存在合法的选择。一样的,如果出现次数最多的元素的出现次数为 $c$,那么如果 $c \leq \left\lfloor \tfrac{n}{m} \right\rfloor$,则对多能选的次数就是 $\left\lfloor \tfrac{n}{m} \right\rfloor$,否则最能选择的次数是 $n - c$。本题中 $m = 2$,$n$ 就是 $i \, x$ 或 $x \, i$  形式的牌的数量。

  再把 $x \, x$ 的牌考虑进来,一个简单的做法就是枚举将多少张 $x \, x$ 的牌归为 $i \, x$ 形式的牌,剩下的则归为 $x \, i$ 形式的牌,这样可以保证了每次都是在同一形式的牌中选择,然后就可以使用上述的方法来计算答案。在枚举的过程中为了能快速求解答案,需要维护每一类型的牌的总数,以及最大的出现次数。

  AC 代码如下,时间复杂度为 $O(n)$:

class Solution {
public:
    int score(vector<string>& cards, char x) {
        array<array<int, 10>, 10> c({});
        for (auto &s : cards) {
            c[s[0] - 'a'][s[1] - 'a']++;
        }
        array<array<int, 2>, 2> p({});
        for (int i = 0; i < 10; i++) {
            if (i == x - 'a') continue;
            p[0][0] += c[x - 'a'][i];
            p[0][1] = max(p[0][1], c[x - 'a'][i]);
            p[1][0] += c[i][x - 'a'];
            p[1][1] = max(p[1][1], c[i][x - 'a']);
        }
        int ret = 0;
        for (int i = 0; i <= c[x - 'a'][x - 'a']; i++) {
            auto get = [&](int a, int b) {
                if (2 * b > a) return a - b;
                return a >> 1;
            };
            int j = c[x - 'a'][x - 'a'] - i;
            ret = max(ret, get(p[0][0] + i, max(p[0][1], i)) + get(p[1][0] + j, max(p[1][1], j)));
        }
        return ret;
    }
};

 

posted @ 2025-08-31 23:14  onlyblues  阅读(17)  评论(0)    收藏  举报
Web Analytics