leetcode
leetcode 851 ~ 900
N 天后的牢房

N 天后的牢房

难度:

标签:

题目描述

代码结果

运行时间: 24 ms, 内存: 0.0 MB


/*
 * 思路:
 * 1. 使用Java Stream和Lambda表达式来实现相同的逻辑。
 * 2. 将每一天的状态用List和Stream的方式来处理。
 * 3. 同样的,使用Set来检测循环,避免不必要的计算。
 */

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class PrisonCellsStream {
    public List<Integer> prisonAfterNDays(List<Integer> cells, int N) {
        Set<List<Integer>> seen = new HashSet<>();
        boolean hasCycle = false;
        int cycle = 0;

        for (int i = 0; i < N; i++) {
            List<Integer> next = nextDay(cells);
            if (!seen.contains(next)) {
                seen.add(next);
                cycle++;
            } else {
                hasCycle = true;
                break;
            }
            cells = next;
        }

        if (hasCycle) {
            N %= cycle;
            for (int i = 0; i < N; i++) {
                cells = nextDay(cells);
            }
        }

        return cells;
    }

    private List<Integer> nextDay(List<Integer> cells) {
        return Arrays.asList(0, 0, 1, 1, 0, 0, 0, 0).stream()
            .map(i -> (i > 0 && i < cells.size() - 1 && cells.get(i - 1).equals(cells.get(i + 1))) ? 1 : 0)
            .collect(Collectors.toList());
    }
}

解释

方法:

题解通过模拟牢房状态的变化,并使用哈希表来检测循环出现的状态,从而优化长周期的模拟过程。首先,算法模拟了牢房状态的每日变化,根据题目规则更新每个牢房。然后,使用一个元组来存储每日牢房的状态,用哈希表记录每个状态第一次出现的天数。如果某个状态已经在哈希表中,则意味着找到了循环周期,可以停止模拟。最后,根据天数 n 与周期长度,利用取余操作确定最终的牢房状态。

时间复杂度:

O(1)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么第一个和最后一个牢房的状态在每一天的更新中始终设为0?
根据题目的规则,牢房状态的更新依赖于相邻两个牢房的状态。对于第一个和最后一个牢房,由于它们分别只有右侧和左侧邻居,不存在两个有效的相邻牢房,因此在模拟状态更新时,无法按照正常规则进行更新。为了简化处理,直接将这两个牢房的状态设置为0。这种处理方式符合题目中对边界情况的默许规则,即边界外没有牢房被视为状态为0。
🦆
题解中提到了状态循环的可能性,具体是如何判断状态开始循环的?
在题解中,使用哈希表来记录每一个牢房状态第一次出现的天数。每次生成新的牢房状态后,会将其转换为元组形式并检查这个状态是否已存在于哈希表中。如果这个状态之前已被记录,那么意味着状态开始重复,从而形成了一个循环。由于状态重复出现的那一天与这一状态首次出现的天数之间,牢房的变化状态将会周期性重复,因此一旦检测到重复状态,就可以确定状态的循环周期已经形成。
🦆
在题解的逻辑中,当找到循环时如何计算剩余天数和循环周期之间的关系,并确定最终状态?
一旦确定了循环周期,题解首先计算出循环开始前非循环状态的天数(即首次出现重复状态的天数与循环周期的关系)。当总天数n小于循环开始的天数时,直接从记录的状态中获取第n天的状态。如果n大于或等于循环开始的天数,首先确定循环周期的长度,然后使用 n 对循环周期长度进行取余操作,得到的结果指出在循环周期中的具体位置。最后,根据这个位置从循环周期中的状态列表获取最终的牢房状态。

相关问题