题目描述
你正在和你的朋友玩 猜数字(Bulls and Cows)游戏:你写下一个数字让你的朋友猜。每次他猜测后,你给他一个提示,告诉他有多少位数字和确切位置都猜对了(称为“Bulls”, 公牛),有多少位数字猜对了但是位置不对(称为“Cows”, 奶牛)。你的朋友将会根据提示继续猜,直到猜出秘密数字。
请写出一个根据秘密数字和朋友的猜测数返回提示的函数,用 A
表示公牛,用 B
表示奶牛。
请注意秘密数字和朋友的猜测数都可能含有重复数字。
样例
输入:secret = "1807", guess = "7810"
输出:"1A3B"
解释:1 公牛和 3 奶牛。公牛是 8,奶牛是 0, 1 和 7。
输入:secret = "1123", guess = "0111"
输出:"1A1B"
解释:朋友猜测数中的第一个 1 是公牛,第二个或第三个 1 可被视为奶牛。
说明
- 你可以假设秘密数字和朋友的猜测数都只包含数字,并且它们的长度永远相等。
算法
(模拟) $O(n)$
- 首先使用一遍循环统计
bulls
的数量,并且记录下第一个字符串中出现数字的数量。 - 第二次遍历第二个字符串,统计第二个字符串中每个数字是否在第一个字符串中出现过。若出现过,则
cows
加 1,数字的数量减 1。 - 最终的
cows = cows - bulls
。
时间复杂度
- 遍历两次字符串,时间复杂度为 $O(n)$。
空间复杂度
- 仅需要常数的额外空间存储 10 个数字是否出现过。
C++ 代码
class Solution {
public:
string getHint(string secret, string guess) {
int n = secret.length(), bulls = 0, cows = 0;
vector<int> vis(10, 0);
for (int i = 0; i < n; i++) {
vis[secret[i] - '0']++;
if (secret[i] == guess[i])
bulls++;
}
for (int i = 0; i < n; i++)
if (vis[guess[i] - '0'] > 0) {
cows++;
vis[guess[i] - '0']--;
}
return to_string(bulls) + "A" + to_string(cows - bulls) + "B";
}
};