Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

822. Card Flipping Game - Leetcode Solution

Problem Description

In the Card Flipping Game problem, you are given two integer arrays, fronts and backs, each of length n. Each index i represents a card: fronts[i] is the number on the front of the card, and backs[i] is the number on the back. You can choose any card and flip it, swapping its front and back numbers.

Your goal is to pick any number that appears on the front or back of any card, such that after possibly flipping any cards, this number does not appear on the front of any card. Among all such numbers, return the minimum possible number. If no such number exists, return 0.

  • You may flip any card any number of times (including zero).
  • Each card can be flipped independently.
  • If a number appears on both sides of the same card, it is considered "invalid" for the answer.

Constraints:

  • 1 <= fronts.length == backs.length <= 1000
  • 1 <= fronts[i], backs[i] <= 2000

Thought Process

At first glance, it might seem like we need to check all possible combinations of flips, but this would be too slow. If we try to brute-force all flip combinations, the number of possibilities grows exponentially with the number of cards.

However, let's think more carefully. Our goal is to find a number that could end up only on the back sides after flipping — that is, after possibly flipping some cards, this number should not be on the front of any card.

But, if a number appears on both sides of the same card, no matter how we flip that card, that number will always be on the front or back. Therefore, such numbers can never be "hidden" from the front, so we must exclude them.

So, the task becomes: among all numbers that appear on some card (either front or back), what is the smallest number that is not on the front of any card after flipping, and is also not "invalid" (i.e., doesn't appear on both sides of the same card).

This suggests we should identify all invalid numbers first, then look for the smallest valid number that can be hidden from all fronts.

Solution Approach

  • Step 1: Identify Invalid Numbers
    • For each card, if fronts[i] == backs[i], add that number to a set of "invalid" numbers. These are numbers that cannot be hidden from the front, regardless of flipping.
  • Step 2: Gather All Candidate Numbers
    • Make a set of all numbers that appear on either the front or back of any card.
  • Step 3: Find the Minimum Valid Number
    • For each candidate number, if it is not in the set of invalid numbers, consider it as a possible answer.
    • Choose the smallest such number.
  • Step 4: Return the Result
    • If no such valid number exists, return 0.
    • Otherwise, return the minimum valid number found.

We use sets for efficient lookups and to avoid duplicates. This approach ensures we only consider valid numbers and ignore those that are impossible to hide from the front.

Example Walkthrough

Example Input: fronts = [1,2,4,4,7], backs = [1,3,4,1,3]

  1. Step 1: Identify Invalid Numbers
    Go through each card:
    • Card 0: fronts[0]=1, backs[0]=1 → 1 is invalid
    • Card 1: 2 ≠ 3 → nothing added
    • Card 2: 4=4 → 4 is invalid
    • Card 3: 4≠1 → nothing added
    • Card 4: 7≠3 → nothing added
    So, invalid numbers = {1, 4}
  2. Step 2: Gather All Candidates
    All numbers on fronts or backs: {1,2,3,4,7}
  3. Step 3: Find Minimum Valid Number
    Candidates not in invalid set: {2,3,7}
    • 2: appears on front, but can we flip it away? Yes, if we flip card 1, 2 goes to back, 3 to front.
    • 3: appears on back of card 1 and 4, not on any front.
    • 7: only on front of card 4.
    But, since we can flip any card, we can try to hide 2 and 3 from all fronts.
    • 2: If we flip card 1, 2 disappears from all fronts.
    • 3: Already not on any front.
    So, the minimum is 2.
  4. Step 4: Return Result
    Return 2.

Code Implementation

class Solution:
    def flipgame(self, fronts, backs):
        invalid = set()
        for f, b in zip(fronts, backs):
            if f == b:
                invalid.add(f)
        candidates = set(fronts) | set(backs)
        ans = float('inf')
        for x in candidates:
            if x not in invalid:
                ans = min(ans, x)
        return 0 if ans == float('inf') else ans
      
class Solution {
public:
    int flipgame(vector<int>& fronts, vector<int>& backs) {
        unordered_set<int> invalid;
        for (int i = 0; i < fronts.size(); ++i) {
            if (fronts[i] == backs[i]) invalid.insert(fronts[i]);
        }
        int ans = INT_MAX;
        for (int x : fronts) {
            if (!invalid.count(x)) ans = min(ans, x);
        }
        for (int x : backs) {
            if (!invalid.count(x)) ans = min(ans, x);
        }
        return ans == INT_MAX ? 0 : ans;
    }
};
      
class Solution {
    public int flipgame(int[] fronts, int[] backs) {
        Set<Integer> invalid = new HashSet<>();
        for (int i = 0; i < fronts.length; i++) {
            if (fronts[i] == backs[i]) invalid.add(fronts[i]);
        }
        int ans = Integer.MAX_VALUE;
        for (int x : fronts) {
            if (!invalid.contains(x)) ans = Math.min(ans, x);
        }
        for (int x : backs) {
            if (!invalid.contains(x)) ans = Math.min(ans, x);
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }
}
      
var flipgame = function(fronts, backs) {
    let invalid = new Set();
    for (let i = 0; i < fronts.length; i++) {
        if (fronts[i] === backs[i]) invalid.add(fronts[i]);
    }
    let ans = Infinity;
    for (let x of fronts.concat(backs)) {
        if (!invalid.has(x)) ans = Math.min(ans, x);
    }
    return ans === Infinity ? 0 : ans;
};
      

Time and Space Complexity

  • Brute-Force Approach:
    • Would involve checking all possible flip combinations (2n), which is infeasible for large n.
    • Time Complexity: O(2n)
  • Optimized Approach (used above):
    • Identifying invalid numbers: O(n)
    • Gathering all candidates: O(n)
    • Finding the minimum valid number: O(n)
    • Total Time Complexity: O(n)
    • Space Complexity: O(n) for sets used to store invalid numbers and candidates.

This efficiency is possible because we avoid simulating all flip combinations and instead use set operations to filter out impossible choices.

Summary

The Card Flipping Game problem is elegantly solved by observing that numbers appearing on both sides of the same card can never be "hidden" from the front, regardless of flips. By filtering out these invalid numbers and then finding the smallest candidate number from the remaining numbers, we efficiently achieve the solution in linear time. This approach avoids brute-force and leverages set operations for clarity and speed.