每日一题:时尚圈的衣着稳定问题 | 豆包MarsCode AI 刷题

176 阅读5分钟

每日一题:时尚圈的衣着稳定问题 | 豆包MarsCode AI 刷题

问题描述

小U在时尚圈组织了一场“校服日”活动,有 n 名学生围成一圈参加活动。每位学生都穿着白色或黑色的校服,白色用 0 表示,黑色用 1 表示。每一天,如果某个学生发现自己和相邻的两位学生穿着相同颜色的校服,那么他会在第二天更换成另一种颜色的校服;否则,他会保持不变。

你的任务是帮助小U判断,在第几天学生们的穿着会达到稳定状态——即某一天后,所有学生的穿着不再发生任何变化。同时,你还需要计算在稳定后,有多少学生的校服颜色与其相邻的同学不同,这些学生被称为“时尚达人”。

最终你需要返回一个包含两个元素的数组:

  • 第一个数字表示稳定下来的天数。如果永远无法稳定,则输出 -1
  • 第二个数字表示稳定后成为“时尚达人”的学生人数。如果永远无法稳定,则输出 -1

测试样例

样例1:

输入:n = 4 ,data = "0000" 输出:[-1, -1]

样例2:

输入:n = 4 ,data = "1110" 输出:[2, 4]

样例3:

输入:n = 6 ,data = "010101" 输出:[1, 6]

问题分析

1. 初始化
current_state = list(data)
days = 0
max_days = 100  # 限制最大天数,防止无限循环
  • current_state:将传入的字符串 data 转换成列表形式,便于后续修改。
  • days:用来记录模拟的天数。
  • max_days:设定一个最大天数的限制,以防止无限循环。如果经过 max_days 次循环仍然没有稳定,则返回 [-1, -1]
2. 模拟每一天的变化
while days < max_days:
    new_state = current_state.copy()
    change_occurred = False
  • 使用 while 循环模拟每一天的变化。days < max_days 确保我们不会无限循环。
  • new_state:每天的变化后的校服状态,初始化为当前状态的副本。这样可以避免直接在原始 current_state 上修改,造成修改影响下一次的计算。
  • change_occurred:标志变量,表示当天是否有任何学生改变了校服。如果当天没有任何变化,则说明已经达到了稳定状态。
3. 逐个学生判断是否更换校服
for i in range(n):
    left = current_state[(i - 1) % n]  # 左边的学生
    right = current_state[(i + 1) % n]  # 右边的学生
​
    if current_state[i] == left and current_state[i] == right:
        new_state[i] = '1' if current_state[i] == '0' else '0'
        change_occurred = True
  • for i in range(n):遍历每个学生。
  • leftright 分别表示该学生左边和右边的学生。通过使用 (i - 1) % n(i + 1) % n 来处理圆圈的情况,确保循环的学生能够与第一个和最后一个学生相邻。
  • 判断 current_state[i] == left and current_state[i] == right:如果左右邻居的校服颜色相同,那么该学生会更换校服。更换后的颜色是 '1''0',取反原来的颜色。
  • 如果有更换,设置 change_occurred = True,表示当天有变化。
4. 判断是否达到稳定
days += 1
current_state = new_state
​
if not change_occurred:
    break  # 没有变化,达到稳定状态
  • days += 1:每天增加 1。
  • current_state = new_state:将当天的状态更新为新的状态。
  • 如果当天没有任何变化(即 change_occurredFalse),则说明已经达到了稳定状态,跳出循环。
5. 判断是否达到最大天数
if days == max_days:
    return [-1, -1]  # 永远无法稳定
  • 如果循环超过了最大天数 max_days 仍然没有稳定状态,返回 [-1, -1],表示无法稳定。
6. 计算时尚达人
fashionistas = 0
for i in range(n):
    if current_state[i] != current_state[(i - 1) % n] and current_state[i] != current_state[(i + 1) % n]:
        fashionistas += 1
  • fashionistas 变量用来记录时尚达人的数量。

  • 遍历每个学生,检查学生的穿着是否与左右邻居不同。如果不同,则该学生是时尚达人。

    • 判断条件 current_state[i] != current_state[(i - 1) % n] and current_state[i] != current_state[(i + 1) % n]
7. 返回结果
return [days, fashionistas]
  • 返回一个列表,包含两个元素:

    • days:稳定所需的天数。
    • fashionistas:稳定状态下,时尚达人的数量。

代码总结

  1. 模拟变化:每一天更新学生的穿着状态,直到没有学生再变化或超过最大天数限制。
  2. 稳定判断:通过 change_occurred 判断是否发生了变化,若没有变化则说明已经稳定。
  3. 时尚达人计算:在稳定状态下,遍历每个学生,统计那些穿着与邻居不同的学生。

时间复杂度分析

  • 每一天需要遍历 n 个学生,判断他们是否更换校服。
  • 最多循环 max_days 次,最终时间复杂度是 O(n * max_days),其中 max_days 默认设置为 100。
  • 对于大多数情况,max_days 不会用尽,因此通常情况是 O(n)。

完整代码

def solution(n, data):
    current_state = list(data)
    days = 0
    max_days = 100  # 限制最大天数,防止无限循环
    
    while days < max_days:
        new_state = current_state.copy()
        change_occurred = False
        
        for i in range(n):
            left = current_state[(i - 1) % n]  # 左边的学生
            right = current_state[(i + 1) % n]  # 右边的学生
            
            if current_state[i] == left and current_state[i] == right:
                new_state[i] = '1' if current_state[i] == '0' else '0'
                change_occurred = True
        
        days += 1
        current_state = new_state
        
        if not change_occurred:
            break  # 没有变化,达到稳定状态
    
    if days == max_days:
        return [-1, -1]  # 永远无法稳定
    
    # 计算时尚达人
    fashionistas = 0
    for i in range(n):
        if current_state[i] != current_state[(i - 1) % n] and current_state[i] != current_state[(i + 1) % n]:
            fashionistas += 1
    
    return [days, fashionistas]
 
# 测试用例
if __name__ == "__main__":
    print(solution(4, "0000") == [-1, -1]) 
    print(solution(4, "1110") == [2, 4])  
    print(solution(6, "010101") == [1, 6])