[LeetCode]52. Bulls and Cows猜数字游戏
You are playing the following Bulls and Cows game with your friend: You write a 4-digit secret number and ask your friend to guess it. Each time your friend guesses a number, you give a hint. The hint tells your friend how many digits are in the correct positions (called "bulls") and how many digits are in the wrong positions (called "cows"). Your friend will use those hints to find out the secret number.
For example:
Secret number: "1807" Friend's guess: "7810"
Hint: 1
bull and 3
cows. (The bull is 8
, the cows are 0
, 1
and 7
.)
Write a function to return a hint according to the secret number and friend's guess, use A
to indicate the bulls and B
to indicate the cows. In the above example, your function should return "1A3B"
.
Please note that both secret number and friend's guess may contain duplicate digits, for example:
Secret number: "1123" Friend's guess: "0111"
In this case, the 1st 1
in friend's guess is a bull, the 2nd or 3rd 1
is a cow, and your function should return "1A1B"
.
You may assume that the secret number and your friend's guess only contain digits, and their lengths are always equal.
Credits:
Special thanks to @jeantimex for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
解法:有一个四位数字,你猜一个结果,然后根据你猜的结果和真实结果做对比,提示有多少个数字和位置都正确的叫做bulls,还提示有多少数字正确但位置不对的叫做cows。因此我们首先统计猜对了几个数字,然后统计有几个猜对的数字在正确的位置上。
class Solution { public: string getHint(string secret, string guess) { int n = secret.size(), bulls = 0, total = 0; vector<int> sv(10, 0), gv(10, 0); for(int i = 0; i < n; ++i) { ++sv[secret[i] - '0']; ++gv[guess[i] - '0']; } for(int i = 0; i < 10; ++i) total += min(sv[i], gv[i]); for(int i = 0; i < n; ++i) if(secret[i] == guess[i]) ++bulls;
return to_string(bulls) + 'A' + to_string(total - bulls) + 'B'; } };
上面的解法可以简化:首先在一次循环中找出所有bulls,即数字与位置均正确的个数,同时在这个过程中可以记录下非bulls时secret的分布情况;然后在第二次循环中就可以根据secret的分布情况统计cows的个数了。
class Solution { public: string getHint(string secret, string guess) { int n = secret.size(), bulls = 0, cows = 0; vector<int> v(10, 0); for(int i = 0; i < n; ++i) { if(guess[i] == secret[i]) ++bulls; else ++v[secret[i] - '0']; //注意只在非bulls时才记录 } for(int i = 0; i < n; ++i) { if(guess[i] != secret[i] && v[guess[i] - '0'] != 0) { ++cows; --v[guess[i] - '0']; } } return to_string(bulls) + "A" + to_string(cows) + "B"; } };
再精简,使用一次循环解决。在处理不是bulls的位置时,如果secret当前位置数字的映射值小于0,则表示其在guess中出现过,cows自增1,然后映射值加1,如果guess当前位置的数字的映射值大于0,则表示其在secret中出现过,cows自增1,然后映射值减1。
class Solution { public: string getHint(string secret, string guess) { int n = secret.size(), bulls = 0, cows = 0; vector<int> v(10, 0); for(int i = 0; i < n; ++i) { if(guess[i] == secret[i]) ++bulls; else { if(v[guess[i] - '0']-- > 0) ++cows; if(v[secret[i] - '0']++ < 0) ++cows; } } return to_string(bulls) + "A" + to_string(cows) + "B"; } };
参考:http://www.cnblogs.com/grandyang/p/4929139.html