leecode299猜数字游戏
(注:开头的一段注释为作者阅读代码理解笔记)
你在和朋友一起玩 猜数字(Bulls and Cows)游戏,该游戏规则如下:
你写出一个秘密数字,并请朋友猜这个数字是多少。
朋友每猜测一次,你就会给他一个提示,告诉他的猜测数字中有多少位属于数字和确切位置都猜对了(称为“Bulls”, 公牛),有多少位属于数字猜对了但是位置不对(称为“Cows”, 奶牛)。
朋友根据提示继续猜,直到猜出秘密数字。
请写出一个根据秘密数字和朋友的猜测数返回提示的函数,返回字符串的格式为 xAyB ,x 和 y 都是数字,A 表示公牛,用 B 表示奶牛。
xA 表示有 x 位数字出现在秘密数字中,且位置都与秘密数字一致。
yB 表示有 y 位数字出现在秘密数字中,但位置与秘密数字不一致。
请注意秘密数字和朋友的猜测数都可能含有重复数字,每位数字只能统计一次。(刚开始没看见备注,犯错了
题目标签:哈希表
首次代码
//数字要求,出现在秘密数字中
//
class Solution {
public String getHint(String secret, String guess) {
int numA=0,numB=0,i=0;
for(i=0;i<secret.length()&&i<guess.length();i++)
{
if (secret.indexOf(guess.charAt(i))!=-1)//数字猜对了
{
if (secret.charAt(i)==guess.charAt(i))//数字对且位置对
numA++;
else
numB++;
//数字多了的情况:1123和0111应该输出1A1B输出1A2B
//secret=secret.replaceFirst(guess.substring(i,i+1),"c");//替换对应过的数字,置为字母,等价于去除
// 解决数字多了法二(2)result=result+guess.substring(i,i+1);
// if (secret.indexOf(guess.charAt(i))!=-1&&result.indexOf(guess.charAt(i))==-1)//数字猜对了
}
}
if(secret.length()<guess.length())
{
i=secret.length();
for(;i<guess.length();i++){
if (secret.indexOf(guess.charAt(i))!=-1)
numB++;
}
}
String result=numA+"A"+numB+"B";
return result;
}
}
法二bug
输入:
“1123” “0111”
输出
“1A0B”
预期结果
“1A1B”
大佬题解
public String getHint(String secret, String guess) {
StringBuilder sb = new StringBuilder();
int a = 0, b = 0;
int[] s = new int[10];//注:判断数字,而数字只有0-9,所以申请一个10长度数组
int[] g = new int[10];
for (int i = 0; i < secret.length(); i++) {
s[secret.charAt(i) - '0']++;//secret.charAt(i):’2‘ - '0'就是字符2对应的数字
g[guess.charAt(i) - '0']++;
a += secret.charAt(i) == guess.charAt(i) ? 1 : 0;
}
for (int i = 0; i < s.length; i++)
b += Math.min(s[i], g[i]);
return sb.append(a).append("A").append(b - a).append("B").toString();
}
第一个for循环用两个数组分别统计数字的个数并对比,如果相同则公牛’a’+1,第二个for循环取数组中的数做对比取最小值,得出两个数一共有b个数相同,最后字符串拼接a’A’(b-a)'B’得到答案
这道题就是做对比,位置相同数字相同就公牛+1,数字相同但位置不同就母牛+1
感谢你的解答!对于a是很好理解的,位置和数字都一样的就累加1即可!
但是对于b就有点困惑:首先s[],g[]保存的是两个数中每一个数字出现的次数,那么对于同一个数字i来说,取这两者的较小者x就是数字i在这两个数中都至少出现了x次。
(注:s[]中出现,g中未出现,取最小值0,s[]中出现,g中出现,则有位置对和不对,都加起来,最后减去位置对的)
哦哦写到这里就懂了,除了x次,剩余的那些次都是数字不相同的,可以直接不用考虑!多谢了
大佬代码2
class Solution {
public String getHint(String secret, String guess) {
int[] nums = new int[10];
int countA = 0, countB = 0;
for (int i = 0; i < secret.length(); i++) {
if(secret.charAt(i) == guess.charAt(i)) countA++;
//注:位置和数字都相同
else{
//注:同一个位置,数字不同
if (nums[guess.charAt(i) - '0']-- > 0) countB++;
//--,先判断再减法,猜到这个数字,则这个数字对应值减一,初始都为0,如果之前秘密其他位置未存在这个数字,则不满足,秘密存在这个数字,则满足
if(nums[secret.charAt(i) - '0']++ < 0) countB++;
//先判断再加法,秘密存在这个数字,则这个数字对应数组值加一,如果其他位置猜到这个数字则可以通过上一个if判定
//因为已经是else的情况,所以不存在位置数字都相同
}
}
return countA + "A" + countB + "B";
}
}
hello world
英文模式下3个tab键上反引号进入代码块模式
class Solution {
public String getHint(String secret, String guess) {
char[] sc = secret.toCharArray();
char[] gc = guess.toCharArray();
int[] temp = new int[10];
int aNumber = 0;
int bNumber = 0;
for(int i = 0; i < sc.length; i++){
if(sc[i] == gc[i]){
aNumber++;
}
if(temp[sc[i] - '0'] < 0){
bNumber++;
}
temp[sc[i] - '0']++;
if(temp[gc[i] - '0'] > 0){
bNumber++;
}
temp[gc[i] - '0']--;
}
return aNumber + "A" + (bNumber - aNumber) + "B";
}
}
思路:此题需要统计两类情况,一类是同一位置相等字符的个数,第二类是数字对了但是位置不对(注意:此类一定要去除掉第一类的情况,优先考虑第一类其次才是第二类)对于第一类很好进行统计,只需要比较对应位置即可,对于第二类,我们可以采用两重循环的遍历方法,不过这样效率太低,由于字符串里面只有数字,所以我们可以采用哈希表的方法来进行一个映射,我们首先把第一个字符串里面的字符与字符出现的次数放入哈希表中即map[secret[i]-‘0’]++;,然后再遍历另一个字符串,每遍历一个字符在哈希表中寻找如果找得到就对这个字符所对应的次数减一,然后再把统计数字加一。这样就可以统计第二类的字符了,不过这样不加任何处理就会导致上面说到的的第二类包含第一类的情况(位置相同的字符,我们第一类统计了第二类也统计了),我们可以在统计第一类的时候就将其放入哈希表中,这样可以如果是第一类的我们就不将其放入哈希表并且把这个字符换成一个非字符(作为一个标志为,这样就可以在统计第二类的情况下,知道这个字符是不是第一类已经统计了的,如果统计了我们就不管了跳过即可。)
class Solution {
public:
string getHint(string secret, string guess) {
int* map= new int[10]();
int A = 0;
int B = 0;
string res;
for(int i = 0 ;i < secret.length(); i++)
{
if(secret[i]==guess[i]){A++;guess[i] = 'A';continue;}
map[secret[i]-'0']++;
}
for(int i = 0 ;i < secret.length(); i++)
if(guess[i]=='A')continue;
else if(map[guess[i]-'0']>0){B++;map[guess[i]-'0']--;}
res.append(to_string(A)+"A"+to_string(B)+"B");
return res;
}
};
涉及java知识介绍
大佬题解二的Stringbuilder