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)

时间复杂度: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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值