• leetcode - 22 672. 灯泡开关 Ⅱ


    房间中有 n 只已经打开的灯泡,编号从 1 到 n 。墙上挂着 4 个开关 。

    这 4 个开关各自都具有不同的功能,其中:

    开关 1 :反转当前所有灯的状态(即开变为关,关变为开) 开关 2 :反转编号为偶数的灯的状态(即 2, 4, …) 开关 3
    :反转编号为奇数的灯的状态(即 1, 3, …) 开关 4 :反转编号为 j = 3k + 1 的灯的状态,其中 k = 0, 1,
    2, …(即 1, 4, 7, 10, …) 你必须 恰好 按压开关 presses 次。每次按压,你都需要从 4
    个开关中选出一个来执行按压操作。

    给你两个整数 n 和 presses ,执行完所有按压之后,返回 不同可能状态 的数量。

    来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/bulb-switcher-ii
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 提示:

    1 <= n <= 1000 0 <= presses <= 1000

    一开始写了一个最简单的未剪枝的dfs方法梳理思路

    class Solution:
        def flipLights(self, n: int, presses: int) -> int:
            if presses==0:
                return 1
            ans = set()
            def flip_1(state):
                for id, num in enumerate(state):
                    state[id] = "1" if state[id] == "0" else "0"
                # print(state)
                return "".join(state)
            def flip_2(state):
                for id, num in enumerate(state):
                    if id%2 == 1:
                        state[id] = "1" if state[id] == "0" else "0"
                # print(state)
                return "".join(state)
            def flip_3(state):
                for id, num in enumerate(state):
                    if id%2 == 0:
                        state[id] = "1" if state[id] == "0" else "0"
                # print(state)
                return "".join(state)
            def flip_4(state):
                for id, num in enumerate(state):
                    if id%3 == 0:
                        state[id] = "1" if state[id] == "0" else "0"
                # print(state)
                return "".join(state)
            def flips(states, press):
                nonlocal ans
                state = list(states)
                if press == 1:
                    ans.add(flip_1(state))
                    ans.add(flip_2(state))
                    ans.add(flip_3(state))
                    ans.add(flip_4(state))
                else:
                    flips(flip_1(state), press-1)
                    flips(flip_2(state), press-1)
                    flips(flip_3(state), press-1)
                    flips(flip_4(state), press-1)
            flips("0"*n, presses)
            return len(ans)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    时间复杂度:O( 4 p r e s s e s 4^{presses} 4presses)

    空间复杂度:O( 4 n 4^n 4n)

    明显可以看出在n和presses最高,可以达到1000时,是完全超时的,因此需要找到更简单的剪枝。
    记四个操作分别为flip1到flip4,各类操作形成的符号串为 f l i p i ∗ f l i p j ⋯ ∗ f l i p k flipi*flipj\cdots*flipk flipiflipjflipk。我们很容易注意到 flip2和flip3是可交换的操作。因此经过仔细观察引申出来,所有的flip对于结果来说都是可交换的,因此我们只需要考虑 ∏ i 1 + i 2 + i 3 + i 4 = p r o c e s s e s ( f l i p 1 ) i 1 ( f l i p 2 ) i 2 ( f l i p 3 ) i 3 ( f l i p 4 ) i 4 \prod \limits_{i_1+i_2+i_3+i_4=processes} (flip1)^{i_1}(flip2)^{i_2}(flip3)^{i_3}(flip4)^{i_4} i1+i2+i3+i4=processes(flip1)i1(flip2)i2(flip3)i3(flip4)i4的形式即可,又因为按钮操作本质上是一个可逆操作,其逆为本身,因此只需要关注 i k i_k ik的奇偶性即可,因此形式转化为 ∏ i 1 + i 2 + i 3 + i 4 = p r o c e s s e s ( f l i p 1 ) i 1 % 2 ( f l i p 2 ) i 2 % 2 ( f l i p 3 ) i 3 % 2 ( f l i p 4 ) i 4 % 2 \prod \limits_{i_1+i_2+i_3+i_4=processes} (flip1)^{i_1\%2}(flip2)^{i_2\%2}(flip3)^{i_3\%2}(flip4)^{i_4\%2} i1+i2+i3+i4=processes(flip1)i1%2(flip2)i2%2(flip3)i3%2(flip4)i4%2 f l i p 2 ∗ f l i p 3 = f l i p 1 flip2*flip3=flip1 flip2flip3=flip1
    因此我们得到最多只有8中情况,列出对应情况即可,为O(1)复杂度

    class Solution:
        def flipLights(self, n: int, presses: int) -> int:
            if presses == 0:
                return 1
            if n > 2:
                if presses == 1:
                    return 4
                if presses == 2:
                    return 6 + 1
                if presses == 3:
                    return 4 + 4 
                if presses == 4:
                    return 6 + 2
                return comb(4, 2) + 2
            elif n == 2:
                if presses == 1:
                    return 3 
                if presses == 2:
                    return 3 + 1
                if presses == 3:
                    return 3 + 1
                return 4
            return 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    论文的框架和逻辑如何把握?
    [工业自动化-7]:西门子S7-15xxx编程 - PLC主站 - 电源模块
    【ESP 保姆级教程】疯狂Node.js服务器篇 ——程序员的浪漫,给女朋友做个3d相册,实现公网访问(不需要ESP)
    react源码分析:深度理解React.Context
    mysql常用命令
    深度神经网络的训练过程,深度神经网络如何训练
    CTF取证技术实战,图片、文件、流等相关内容的取证技术
    轻松一刻|Walrus CLI与CI/CD工具集成,轻松部署2048游戏
    Golang 并发&同步的详细原理和使用技巧
    联邦学习fate框架入门
  • 原文地址:https://blog.csdn.net/qq_42906799/article/details/126878541