题目解析
在这个问题中,我们需要模拟学生们的校服颜色变化过程。每位学生会根据自己和相邻学生的校服颜色决定是否更换自己的颜色。我们需要找到稳定状态,即在某一天后,所有学生的校服颜色不再变化,并计算在这个稳定状态下,多少学生的校服颜色与相邻的学生不同。
思路
- 初始化:将输入的校服颜色字符串转换为字符数组,记录天数。
- 循环模拟:使用一个无限循环来模拟每一天的变化:
-
创建一个新的状态数组 nextState,用于记录第二天的校服颜色。 -
遍历每个学生,检查他们的左右邻居: -
如果左右邻居的颜色与自己相同,则更换颜色。 -
更新天数,并将 nextState 赋值给 students。 -
如果没有任何学生的颜色发生变化,说明达到了稳定状态,跳出循环。
- 判断稳定性:如果天数超过1000天,返回 -1, -1,表示无法稳定。
- 计算时尚达人:遍历最终的 students 数组,计算与相邻学生颜色不同的学生数量。
图解
假设有4名学生,初始状态为 0000:
初始状态:
0 0 0 0
第一天:
0 0 0 0 (没有变化)
稳定状态:无法稳定,返回 [-1, -1]
再假设初始状态为 1110:
初始状态:
1 1 1 0
第一天:
0 0 0 0
第二天:
1 1 1 0 (没有变化)
稳定状态:返回 [2, 4]
代码详解
1.输入
char[] students = data.toCharArray();
int days = 0;
- char[] students = data.toCharArray();:将输入的字符串 data 转换为字符数组 students,每个字符代表一个学生的校服颜色('0' 或 '1')。
- int days = 0;:初始化一个计数器 days,用于记录经过的天数。
2.主循环;状态更新
while (true) {
boolean changed = false;
char[] nextState = students.clone();
for (int i = 0; i < n; i++) {
char left = students[(i - 1 + n) % n];
char right = students[(i + 1) % n];
if (students[i] == left && students[i] == right) {
nextState[i] = (students[i] == '0') ? '1' : '0';
changed = true;
}
}
-
while (true):使用无限循环来模拟每一天的变化,直到达到稳定状态。
-
boolean changed = false;:初始化一个布尔变量 changed,用于标记当天是否有学生的颜色发生变化。
-
char[] nextState = students.clone();:克隆当前的 students 数组,准备记录第二天的状态。
-
for (int i = 0; i < n; i++):遍历每个学生,n 是学生的总数。
-
char left = students[(i - 1 + n) % n]; 和 char right = students[(i + 1) % n];:计算当前学生的左右邻居的颜色,使用模运算处理环形结构,确保索引不会越界。
-
if (students[i] == left && students[i] == right):检查当前学生的颜色是否与左右邻居相同。
-
如果相同,则更换颜色,使用三元运算符 nextState[i] = (students[i] == '0') ? '1' : '0'; 来实现颜色的切换。
-
将 changed 设置为 true,表示当天有变化
3.更新状态和天数
days++;
students = nextState;
-
days++;:增加天数计数。
-
students = nextState;:将 students 更新为 nextState,准备进入下一天的循环。
4.稳定性判断
f (!changed) {
break;
}
if (days > 1000) {
return new int[]{-1, -1};
}
}
-
if (!changed):如果当天没有任何变化,说明达到了稳定状态,使用 break 跳出循环。
-
if (days > 1000):如果经过的天数超过1000,返回 -1, -1,表示无法稳定。
5.统计结果并返回
int fashionistas = 0;
for (int i = 0; i < n; i++) {
char left = students[(i - 1 + n) % n];
char right = students[(i + 1) % n];
if (students[i] != left && students[i] != right) {
fashionistas++;
}
}
return new int[]{days, fashionistas};
}
-
int fashionistas = 0;:初始化时尚达人计数器。
-
for (int i = 0; i < n; i++):遍历最终的学生状态。
-
if (students[i] != left && students[i] != right):检查当前学生的颜色是否与左右邻居不同。
-
如果不同,计数器 fashionistas 加一。
个人思考与分析
这个问题的关键在于如何有效地模拟学生的校服变化。通过使用循环和状态数组,我们能够清晰地跟踪每一天的变化。需要注意的是,循环的终止条件和稳定状态的判断是实现的核心部分。在实际应用中,这种模拟方法可以扩展到其他类似的动态系统中,例如生态系统的变化、社会网络中的信息传播等。