LeetCode-in-Java

3664. Two-Letter Card Game

Medium

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:

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:

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

Example 2:

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

Output: 1

Explanation:

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:

Solution

public class Solution {
    public int score(String[] cards, char x) {
        // store input midway as required
        // counts for "x?" group by second char and "?x" group by first char
        int[] left = new int[10];
        int[] right = new int[10];
        int xx = 0;
        for (String c : cards) {
            char a = c.charAt(0);
            char b = c.charAt(1);
            if (a == x && b == x) {
                xx++;
            } else if (a == x) {
                left[b - 'a']++;
            } else if (b == x) {
                right[a - 'a']++;
            }
        }
        // max pairs inside a group where pairs must come from different buckets:
        // pairs = min(total/2, total - maxBucket)
        int l = 0;
        int maxL = 0;
        for (int v : left) {
            l += v;
            if (v > maxL) {
                maxL = v;
            }
        }
        int r = 0;
        int maxR = 0;
        for (int v : right) {
            r += v;
            if (v > maxR) {
                maxR = v;
            }
        }
        int pairsLeft = Math.min(l / 2, l - maxL);
        int pairsRight = Math.min(r / 2, r - maxR);
        // leftovers after internal pairing
        int leftoverL = l - 2 * pairsLeft;
        int leftoverR = r - 2 * pairsRight;
        int leftovers = leftoverL + leftoverR;
        // First, use "xx" to pair with any leftovers
        int useWithXX = Math.min(xx, leftovers);
        int xxLeft = xx - useWithXX;
        // If "xx" still remain, we can break existing internal pairs:
        // breaking 1 internal pair frees 2 cards, which can pair with 2 "xx" to gain +1 net point
        int extraByBreaking = Math.min(xxLeft / 2, pairsLeft + pairsRight);
        return pairsLeft + pairsRight + useWithXX + extraByBreaking;
    }
}