【Leetcode】672. Bulb Switcher II 灯泡开关 Ⅱ

There is a room with n lights which are turned on initially and 4 buttons on the wall. After performing exactly m unknown operations towards buttons, you need to return how many different kinds of status of the n lights could be.

Suppose n lights are labeled as number [1, 2, 3 ..., n], function of these 4 buttons are given below:

  1. Flip all the lights.
  2. Flip lights with even numbers.
  3. Flip lights with odd numbers.
  4. Flip lights with (3k + 1) numbers, k = 0, 1, 2, ...

Example 1:

Input: n = 1, m = 1.
Output: 2
Explanation: Status can be: [on], [off]

Example 2:

Input: n = 2, m = 1.
Output: 3
Explanation: Status can be: [on, off], [off, on], [off, off]

Example 3:

Input: n = 3, m = 1.
Output: 4
Explanation: Status can be: [off, on, off], [on, off, on], [off, off, off], [off, on, on].

Note: n and m both fit in range [0, 1000].

解法

首先一看,m和n都有1000那么大,我立马放弃了暴力……虽然好像搜索也可以过……?
首先,很容易注意到:

  1. 这些操作的作用顺序与结果无关
  2. 重复2次同一个操作相当于没做操作,所以每个操作只可能有0和1两种状态
  3. 操作2+操作3=操作1

那么最后的状态只取决于这4个操作的状态,所以总共的自变量最多只有16个,而最终灯的状态可能更少。
首先我们想想,m次操作怎么样实现出这16种状态呢?假如我们想得到0001(操作1~4分别做0、0、0、1次),我们只需要把一个1分给操作4,然后剩下的m-1随便分成4个偶数【这个偶数包括0】,只要m-1是偶数,肯定能分出来。

我自己枚举的时候把16个都搞出来了……,按官方解答走捷径叭Orz

另外,由于操作2+操作3=操作1,我们进行主成分提取,总共又可以把自变量空间缩小到以下8个状态:

状态结果条件
0000(=1110)全开【B+C】【m偶,m>=0】或【m奇,m>=3】
0001(=1111)除1,4,7……外开【B+C-A】【m偶,m>=4】或【m奇,m>=1】
0010(=1100)偶开【B】【m偶,m>=2】或【m奇,m>=1】
0100(=1010)奇开【C】【m偶,m>=2】或【m奇,m>=1】
0011(=1101)偶数除4,10……,以及1,7,13……是开着的【(B-A)+(C&A)】【m偶,m>=2】或【m奇,m>=3】
0110(=1000)全关【 ∅ \emptyset 【m偶,m>=2】或【m奇,m>=1】
0101(=1011)奇数除1,7,13……,以及4,10,……开【(C-A)+(B&A)】【m偶,m>=2】或【m奇m>=3】
0111(=1001)1,4,7……开【A】【m偶,m>=2】或【m奇,m>=3】

其中,B代表偶数下标集合,C代表奇数下标集合,A代表3x+1下标集合,中括号【】里表示状态为的下标集合

分析完m对结果的影响之后,我们再分析n对结果的影响。n较小的时候,有的结果表现出来是一样的,这时候状态就不可能是8个了

  1. 分析易知,当ABC互不相同的时候,8个状态各自不同
  2. AB只有n=0时相同,ACn=0,1,2时都相同

所以根据m和n的不同,可以总结出下面的规律:
1

class Solution(object):
    def flipLights(self, n, m):
        """
        :type n: int
        :type m: int
        :rtype: int
        """
        if n==0:
            return 0
        if m==0:
            return 1
        if n==1:
            return 2
        if n==2:
            return 3 if m==1 else 4
        if m==1:
            return 4
        if m==2:
            return 7
        return 8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值