🧠
Optimized Greedy (Check Only Two Candidates)
💡 This approach leverages the insight that only the numbers on the first domino can be the candidates to unify the row, reducing checks from 6 to 2 candidates.
Intuition
Since the final uniform number must appear on every domino's top or bottom, it must be either A[0] or B[0]. Check only these two candidates to minimize rotations.
Algorithm
- Set candidates as A[0] and B[0].
- For each candidate:
- Iterate through all dominoes:
- If neither side has candidate, discard candidate.
- Count rotations needed to make all tops or all bottoms equal to candidate.
- Return minimum rotations among candidates or -1 if none.
💡 This reduces unnecessary checks and speeds up the solution while preserving correctness.
def minDominoRotations(A, B):
def check(x):
rotations_a = rotations_b = 0
for i in range(len(A)):
if A[i] != x and B[i] != x:
return float('inf')
elif A[i] != x:
rotations_a += 1
elif B[i] != x:
rotations_b += 1
return min(rotations_a, rotations_b)
rotations = min(check(A[0]), check(B[0]))
return rotations if rotations != float('inf') else -1
# Driver code
if __name__ == '__main__':
A = [2,1,2,4,2,2]
B = [5,2,6,2,3,2]
print(minDominoRotations(A, B)) # Output: 2
Line Notes
def check(x):Helper function to count rotations for candidate x
if A[i] != x and B[i] != x:If neither side matches candidate, no solution for x
rotations_a += 1Count rotations to make top equal candidate
rotations_b += 1Count rotations to make bottom equal candidate
return min(rotations_a, rotations_b)Return minimal rotations for candidate x
rotations = min(check(A[0]), check(B[0]))Check only two candidates from first domino
return rotations if rotations != float('inf') else -1Return result or -1 if impossible
public class Solution {
public int minDominoRotations(int[] A, int[] B) {
int rotationsA = check(A[0], A, B);
int rotationsB = check(B[0], A, B);
int rotations = Math.min(rotationsA, rotationsB);
return rotations == Integer.MAX_VALUE ? -1 : rotations;
}
private int check(int x, int[] A, int[] B) {
int rotationsA = 0, rotationsB = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] != x && B[i] != x) return Integer.MAX_VALUE;
else if (A[i] != x) rotationsA++;
else if (B[i] != x) rotationsB++;
}
return Math.min(rotationsA, rotationsB);
}
public static void main(String[] args) {
Solution sol = new Solution();
int[] A = {2,1,2,4,2,2};
int[] B = {5,2,6,2,3,2};
System.out.println(sol.minDominoRotations(A, B)); // Output: 2
}
}
Line Notes
int rotationsA = check(A[0], A, B);Check rotations for candidate A[0]
int rotationsB = check(B[0], A, B);Check rotations for candidate B[0]
if (A[i] != x && B[i] != x) return Integer.MAX_VALUE;No solution if neither side matches candidate
rotationsA++;Count rotations to make top equal candidate
rotationsB++;Count rotations to make bottom equal candidate
return Math.min(rotationsA, rotationsB);Return minimal rotations for candidate
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int check(int x, vector<int>& A, vector<int>& B) {
int rotationsA = 0, rotationsB = 0;
for (int i = 0; i < A.size(); i++) {
if (A[i] != x && B[i] != x) return INT_MAX;
else if (A[i] != x) rotationsA++;
else if (B[i] != x) rotationsB++;
}
return min(rotationsA, rotationsB);
}
int minDominoRotations(vector<int>& A, vector<int>& B) {
int rotations = min(check(A[0], A, B), check(B[0], A, B));
return rotations == INT_MAX ? -1 : rotations;
}
int main() {
vector<int> A = {2,1,2,4,2,2};
vector<int> B = {5,2,6,2,3,2};
cout << minDominoRotations(A, B) << endl; // Output: 2
return 0;
}
Line Notes
int rotations = min(check(A[0], A, B), check(B[0], A, B));Check only two candidates from first domino
if (A[i] != x && B[i] != x) return INT_MAX;No solution if neither side matches candidate
rotationsA++;Count rotations to make top equal candidate
rotationsB++;Count rotations to make bottom equal candidate
return min(rotationsA, rotationsB);Return minimal rotations for candidate
var minDominoRotations = function(A, B) {
const check = (x) => {
let rotationsA = 0, rotationsB = 0;
for (let i = 0; i < A.length; i++) {
if (A[i] !== x && B[i] !== x) return Infinity;
else if (A[i] !== x) rotationsA++;
else if (B[i] !== x) rotationsB++;
}
return Math.min(rotationsA, rotationsB);
};
const rotations = Math.min(check(A[0]), check(B[0]));
return rotations === Infinity ? -1 : rotations;
};
// Test
const A = [2,1,2,4,2,2];
const B = [5,2,6,2,3,2];
console.log(minDominoRotations(A, B)); // Output: 2
Line Notes
const check = (x) => {Helper function to count rotations for candidate x
if (A[i] !== x && B[i] !== x) return Infinity;No solution if neither side matches candidate
rotationsA++;Count rotations to make top equal candidate
rotationsB++;Count rotations to make bottom equal candidate
const rotations = Math.min(check(A[0]), check(B[0]));Check only two candidates from first domino
return rotations === Infinity ? -1 : rotations;Return result or -1 if impossible
Only two candidates checked, each requiring one pass over n dominoes, so O(2n) = O(n). Space is constant.
💡 For n=100,000, this means about 200,000 operations, faster than brute force.
Interview Verdict: Accepted
This is the preferred approach in interviews due to its efficiency and simplicity.