957. N 天后的牢房

8 间牢房排成一排,每间牢房不是有人住就是空着。

每天,无论牢房是被占用或空置,都会根据以下规则进行更改:

如果一间牢房的两个相邻的房间都被占用或都是空的,那么该牢房就会被占用。
否则,它就会被空置。
(请注意,由于监狱中的牢房排成一行,所以行中的第一个和最后一个房间无法有两个相邻的房间。)

我们用以下方式描述监狱的当前状态:如果第 i 间牢房被占用,则 cell[i]1,否则 cell[i]0。

根据监狱的初始状态,在 N 天后返回监狱的状况(和上述 N 种变化)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/prison-cells-after-n-days
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

import java.util.HashMap;
import java.util.Map;

class Solution {

    private int toInt(int[] cells) {
        int ans = 0;
        for (int i = 0; i < cells.length; ++i) {
            ans = ans * 2 + cells[i];
        }
        return ans;
    }

    private int[] toArray(int x) {
        int[] ans = new int[8];
        for (int i = 0; i < ans.length; ++i) {
            ans[i] = (x >> (7 - i)) & 1;
        }
        return ans;
    }

    private int[] next(int[] cells) {
        int[] ans = new int[cells.length];
        ans[0] = ans[ans.length - 1] = 0;
        for (int i = 1; i < cells.length - 1; ++i) {
            int sum = cells[i - 1] + cells[i + 1];
            if (sum == 0 || sum == 2) {
                ans[i] = 1;
            }
        }
        return ans;
    }

    private int next(int x) {
        int ans = 0;
        // 0 1 2 3 4 5 6 7
        // 01011001
        for (int i = 1; i < 7; ++i) {
            if (((x >> (8 - i) & 1) ^ (x >> (6 - i) & 1)) == 0)
                ans |= (1 << (7 - i));
        }
        return ans;
    }

    public int[] prisonAfterNDays(int[] cells, int n) {
        int[] hash = new int[256];
        int x = hash[0] = toInt(cells);
        Map<Integer, Integer> map = new HashMap<>();
        map.put(x, 0);
        int index = 1;
        while (index <= n) {
            x = next(x);
            /**
             * 发现循环节
             * 此时最后一个元素的下标为 index - 1, 总元素个数为 index
             */
            if (map.containsKey(x)) {
                break;
            }
            hash[index] = x;
            map.put(x, index++);
        }

        if (index == n + 1) {
            return toArray(hash[index - 1]);
        }

        /**
         * 循环节的第一个元素的下标
         */
        int startIndex = map.get(x);

        /**
         * 循环节的长度
         */
        // 1 2 3 4 5 6 7
        int circleLength = index - startIndex;

        /**
         * 去除前面不是循环节的部分
         */
        n -= (startIndex - 1);

        /**
         * 在循环节的第一个数
         */
        int rank = n % circleLength == 0 ? circleLength : n % circleLength;

        x = hash[startIndex + rank - 1];

        return toArray(x);
    }
}
posted @   Tianyiya  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示