You are given two 0-indexed integer arrays fronts
and backs
of length n
, where the ith
card has the positive integer fronts[i]
printed on the front and backs[i]
printed on the back. Initially, each card is placed on a table such that the front number is facing up and the other is facing down. You may flip over any number of cards (possibly zero).
After flipping the cards, an integer is considered good if it is facing down on some card and not facing up on any card.
Return the minimum possible good integer after flipping the cards. If there are no good integers, return 0
.
Example 1:
Input: fronts = [1,2,4,4,7], backs = [1,3,4,1,3] Output: 2 Explanation: If we flip the second card, the face up numbers are [1,3,4,4,7] and the face down are [1,2,4,1,3]. 2 is the minimum good integer as it appears facing down but not facing up. It can be shown that 2 is the minimum possible good integer obtainable after flipping some cards.
Example 2:
Input: fronts = [1], backs = [1] Output: 0 Explanation: There are no good integers no matter how we flip the cards, so we return 0.
Constraints:
n == fronts.length == backs.length
1 <= n <= 1000
1 <= fronts[i], backs[i] <= 2000
The problem asks to find the minimum "good" integer after flipping some cards. A good integer is defined as a number that appears on the back of at least one card but not on the front of any card.
The solution uses a set s
to store numbers that appear on both the front and back of at least one card. These numbers cannot be good integers because they will always be visible on at least one side, regardless of flipping.
The algorithm iterates through both fronts
and backs
arrays. For each number, it checks if it's present in the s
set. If a number is not in s
, it means it's a potential candidate for a good integer. The algorithm maintains a minimum ans
variable to track the smallest good integer found so far.
After checking all numbers, the minimum good integer (ans
) is returned. If no good integer exists (ans
remains the initial large value), 0 is returned.
The algorithm involves:
s
: This takes O(n) time, where n is the length of the input arrays.fronts
and backs
: This takes O(n) time for each array, totaling O(n) time.s
: Checking if an element is in a set takes O(1) on average (using a hash set).Therefore, the overall time complexity of the algorithm is O(n).
The space complexity is dominated by the set s
. In the worst case, s
could store up to n elements (if all cards have the same number on both sides). Therefore, the space complexity is O(n).
The provided code solutions efficiently implement this approach:
Python:
class Solution:
def flipgame(self, fronts: List[int], backs: List[int]) -> int:
s = {a for a, b in zip(fronts, backs) if a == b} #Efficiently creates the set using set comprehension
return min((x for x in chain(fronts, backs) if x not in s), default=0) #Uses generator expression for efficient iteration and min function to find the minimum
Java:
class Solution {
public int flipgame(int[] fronts, int[] backs) {
Set<Integer> s = new HashSet<>();
int n = fronts.length;
for (int i = 0; i < n; ++i) {
if (fronts[i] == backs[i]) {
s.add(fronts[i]);
}
}
int ans = 9999; //Initialize with a large value
for (int v : fronts) {
if (!s.contains(v)) {
ans = Math.min(ans, v);
}
}
for (int v : backs) {
if (!s.contains(v)) {
ans = Math.min(ans, v);
}
}
return ans % 9999; //Handles potential integer overflow
}
}
C++:
class Solution {
public:
int flipgame(vector<int>& fronts, vector<int>& backs) {
unordered_set<int> s;
int n = fronts.size();
for (int i = 0; i < n; ++i) {
if (fronts[i] == backs[i]) {
s.insert(fronts[i]);
}
}
int ans = 9999;
for (int& v : fronts) {
if (!s.count(v)) {
ans = min(ans, v);
}
}
for (int& v : backs) {
if (!s.count(v)) {
ans = min(ans, v);
}
}
return ans % 9999;
}
};
The other languages (Go, TypeScript, C#) follow similar structures, utilizing their respective sets and min/minimum functions for optimal performance. The % 9999
in some solutions is a safeguard against potential integer overflow, although unlikely given the problem constraints.