Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
You are playing the Bulls and Cows game with your friend.
You write down a secret number and ask your friend to guess what the number is. When your friend makes a guess, you provide a hint with the following info:
Given the secret number secret and your friend's guess guess, return the hint for your friend's guess.
The hint should be formatted as "xAyB", where x is the number of bulls and y is the number of cows. Note that both secret and guess may contain duplicate digits.
Example 1:
Input: secret = "1807", guess = "7810" Output: "1A3B" Explanation: Bulls are connected with a '|' and cows are underlined: "1807" | "7810"
Example 2:
Input: secret = "1123", guess = "0111" Output: "1A1B" Explanation: Bulls are connected with a '|' and cows are underlined: "1123" "1123" | or | "0111" "0111" Note that only one of the two unmatched 1s is counted as a cow since the non-bull digits can only be rearranged to allow one 1 to be a bull.
Constraints:
1 <= secret.length, guess.length <= 1000secret.length == guess.lengthsecret and guess consist of digits only.Problem summary: You are playing the Bulls and Cows game with your friend. You write down a secret number and ask your friend to guess what the number is. When your friend makes a guess, you provide a hint with the following info: The number of "bulls", which are digits in the guess that are in the correct position. The number of "cows", which are digits in the guess that are in your secret number but are located in the wrong position. Specifically, the non-bull digits in the guess that could be rearranged such that they become bulls. Given the secret number secret and your friend's guess guess, return the hint for your friend's guess. The hint should be formatted as "xAyB", where x is the number of bulls and y is the number of cows. Note that both secret and guess may contain duplicate digits.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map
"1807" "7810"
"1123" "0111"
make-number-of-distinct-characters-equal)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #299: Bulls and Cows
class Solution {
public String getHint(String secret, String guess) {
int x = 0, y = 0;
int[] cnt1 = new int[10];
int[] cnt2 = new int[10];
for (int i = 0; i < secret.length(); ++i) {
int a = secret.charAt(i) - '0', b = guess.charAt(i) - '0';
if (a == b) {
++x;
} else {
++cnt1[a];
++cnt2[b];
}
}
for (int i = 0; i < 10; ++i) {
y += Math.min(cnt1[i], cnt2[i]);
}
return String.format("%dA%dB", x, y);
}
}
// Accepted solution for LeetCode #299: Bulls and Cows
func getHint(secret string, guess string) string {
x, y := 0, 0
cnt1 := [10]int{}
cnt2 := [10]int{}
for i, c := range secret {
a, b := int(c-'0'), int(guess[i]-'0')
if a == b {
x++
} else {
cnt1[a]++
cnt2[b]++
}
}
for i, c := range cnt1 {
y += min(c, cnt2[i])
}
return fmt.Sprintf("%dA%dB", x, y)
}
# Accepted solution for LeetCode #299: Bulls and Cows
class Solution:
def getHint(self, secret: str, guess: str) -> str:
cnt1, cnt2 = Counter(), Counter()
x = 0
for a, b in zip(secret, guess):
if a == b:
x += 1
else:
cnt1[a] += 1
cnt2[b] += 1
y = sum(min(cnt1[c], cnt2[c]) for c in cnt1)
return f"{x}A{y}B"
// Accepted solution for LeetCode #299: Bulls and Cows
struct Solution;
impl Solution {
fn get_hint(secret: String, guess: String) -> String {
let s: Vec<char> = secret.chars().collect();
let g: Vec<char> = guess.chars().collect();
let mut bulls = 0;
let mut cows = 0;
let mut s_count = vec![0; 10];
let mut g_count = vec![0; 10];
let n = s.len();
let m = g.len();
for i in 0..n.max(m) {
if i < n.min(m) && s[i] == g[i] {
bulls += 1;
} else {
if i < n {
s_count[(s[i] as u8 - b'0') as usize] += 1;
}
if i < m {
g_count[(g[i] as u8 - b'0') as usize] += 1;
}
}
}
for i in 0..10 {
cows += s_count[i].min(g_count[i]);
}
format!("{}A{}B", bulls, cows)
}
}
#[test]
fn test() {
let secret = "1807".to_string();
let guess = "7810".to_string();
let res = "1A3B".to_string();
assert_eq!(Solution::get_hint(secret, guess), res);
let secret = "1123".to_string();
let guess = "0111".to_string();
let res = "1A1B".to_string();
assert_eq!(Solution::get_hint(secret, guess), res);
}
// Accepted solution for LeetCode #299: Bulls and Cows
function getHint(secret: string, guess: string): string {
const cnt1: number[] = Array(10).fill(0);
const cnt2: number[] = Array(10).fill(0);
let x: number = 0;
for (let i = 0; i < secret.length; ++i) {
if (secret[i] === guess[i]) {
++x;
} else {
++cnt1[+secret[i]];
++cnt2[+guess[i]];
}
}
let y: number = 0;
for (let i = 0; i < 10; ++i) {
y += Math.min(cnt1[i], cnt2[i]);
}
return `${x}A${y}B`;
}
Use this to step through a reusable interview workflow for this problem.
For each element, scan the rest of the array looking for a match. Two nested loops give n × (n−1)/2 comparisons = O(n²). No extra space since we only use loop indices.
One pass through the input, performing O(1) hash map lookups and insertions at each step. The hash map may store up to n entries in the worst case. This is the classic space-for-time tradeoff: O(n) extra memory eliminates an inner loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.