Leetcode刷题-190630

19/06/30

猜数字游戏

猜数字

题目意思大概是两列长度相等的数列,如果第一位称为secret,第二列叫guess,如果对$i \in \{0, … ,secret.length\}$,有$secret[i] = guess[i]$称之为公牛,此时的i记录在公牛集$BullSet$中,有$secret[j] \in guess \land j \notin BullSet \land j \notin CowSet$,称之为奶牛,此时的j记录在奶牛集$CowSet$中。

简单描述题目基本已经把解法说清楚了,模拟即可,一下是模拟的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

public String getHint(String secret, String guess) {
char[] secretArray = secret.toCharArray();
char[] guessArray = guess.toCharArray();

// secret 和 guess 的index可以用作id,故此处是Integer而不是Character
HashSet<Integer> A = new HashSet<>();
HashSet<Integer> B = new HashSet<>();

// 计算公牛
int i = 0;
while (i < guessArray.length) {

if (guessArray[i] == secretArray[i]) {
// 记录在公牛集
A.add(i);
}
i++;
}

// 计算奶牛
for (int j = 0; j < guessArray.length; j++) {
// 在公牛集中忽略
if (A.contains(j)) {
continue;
}
// 遍历secret
for (int k = 0; k < secretArray.length; k++) {
// 不在公牛集而且不在奶牛集
if (!A.contains(k) && !B.contains(k) && guessArray[j] == secretArray[k]) {
// 记录在奶牛集
B.add(k);
break;
}
}
}

return String.format("%dA%dB", A.size(), B.size());
}

很容易理解但是占内存又大时间又久,下面学习一下一个比较快而且很巧妙的解法,copy from the solution。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
   public String getHint(String secret, String guess) {

// ab[0]代表A,ab[1]代表B
int[] ab = new int[2];

// 数列总长
int n = secret.length();

// 当flag,每个数字出现了几次
int[] cnt = new int[10];

// 计算公牛
for (int i = 0; i < n; ++i) {
char s = secret.charAt(i);
char g = guess.charAt(i);

// 符合公牛条件
if (s == g) {
ab[0]++;
continue;
}

// 不符合公牛条件但是在secret中出现的数字需要自增,每出现一个就增加1
cnt[s - '0']++;
}

// 计算奶牛
for (int i = 0; i < n; ++i) {
char s = secret.charAt(i);
char g = guess.charAt(i);

// s != g 判断此位不是公牛位(有可能是奶牛位,继续判断),&&后面的表达式cnt[g - '0'] > 0的含义是“而且还在secret中出现了的数字”,只要大于0,意味着至少还剩了1次可以使用,即符合奶牛要求。此处很巧妙,cnt[index]记录了index在secret中出现了多少次,可以作为奶牛位可以分配多少的依据,从而避免了使用HashSet。
if (s != g && cnt[g - '0'] > 0) {
// 消耗了一个奶牛位的位置所以要自减
cnt[g - '0']--;
ab[1]++;
}
}
return ab[0] + "A" + ab[1] + "B";
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值