先贴一下此题的代码(JAVA版本)
import java.util.*;
public class Main {
public static int[] solution(int n, String data) {
// 将初始状态转换为整数表示
int currentState = 0;
for (char c : data.toCharArray()) {
currentState = (currentState << 1) | (c - '0');
}
// 使用集合记录已经出现过的状态
Set<Integer> seenStates = new HashSet<>();
seenStates.add(currentState);
// 模拟每一天的变化
int days = 1;
int nextState = currentState;
while (true) {
// 计算下一天的状态
for (int i = 0; i < n; i++) {
int left = (i == 0) ? (currentState >> (n-1))&1 : (currentState >> (i-1))&1;
int right = (i == n - 1) ? (currentState >> (0))&1 : (currentState >> (i+1))&1;
int current = (currentState >> i) & 1;
if (left == current && right == current) {
nextState ^= (1 << i); // 改变
}
}
// 检查是否达到稳定状态
if (nextState == currentState) {
int fashionCount = 0;
for (int i = 0; i < n; i++) {
int left = (i == 0) ? (currentState >> (n-1))&1 : (currentState >> (i-1))&1;
int right = (i == n - 1) ? (currentState >> (0))&1 : (currentState >> (i+1))&1;
int current = (currentState >> i) & 1;
if (left != current && right != current) {
fashionCount++;
}
}
return new int[] { days, fashionCount };
}
// 检查新状态是否已经出现过
if (seenStates.contains(nextState)) {
return new int[] { -1, -1 };
}
seenStates.add(nextState);
// 更新当前状态
currentState = nextState;
days++;
}
}
public static void main(String[] args) {
// Add your test cases here
// solution(4, "0000");
System.out.println(java.util.Arrays.equals(solution(4, "0000"), new int[] {
-1, -1 }));
System.out.println(java.util.Arrays.equals(solution(4, "1110"), new int[]{2,
4}));
}
}
思路:
这种判断是否有环的题一般都是将已经出现的状态存储一下,然后一直计算下一状态,如果出现了已经出现过的状态,证明必定是有环的。
此题有一个比较有意思的点是,输入的状态是字符串,但是全是0和1组成的字符串,所以存入set的时候,可以想到通过二进制转化为int类型去存储(当然用字符串存也可以),因为刚好在位运算方面的知识有些薄弱,所以拿这个题练下手。
下面是代码里一些关于位运算的记录:
代码片段1
for (char c : data.toCharArray()) {
currentState = (currentState << 1) | (c - '0');
}
这句代码的意思是,计算字符串data对应的int类型的值。实现方法是,数字不断左移然后加上新的一位(在代码里的体现是|运算符),因为
0|0 = 0
0|1 = 1
即一个数字和0作或运算,还是数字本身。
代码片段2
int left = (i == 0) ? (currentState >> (n-1))&1 : (currentState >> (i-1))&1;
先说这个三目运算符,因为n个同学围成了一个圈,所以当i==0或者当i==n-1的时候,需要对其相邻元素进行单独判断。
其次说这行代码里的位运算,currentState >> (n-1))&1这句代码的意思是,计算currentState这个int类型的值,n-1位二进制是多少(从0开始,从右往左数)。
1&0 = 0
1&1 = 1
为什么这里用与呢?因为不同于代码片段1,我们只需要保留最后一位,和1相与后,除了最后一位其他位必为0。