【2022-09-15每日一题】672. 灯泡开关 Ⅱ

2022-09-15
2分钟阅读时长

2022-09-15每日一题:672. 灯泡开关 Ⅱ

  • 难度:Medium
  • 标签:位运算 、 深度优先搜索 、 广度优先搜索 、 数学

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

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

  • 开关 1 :反转当前所有灯的状态(即开变为关,关变为开)
  • 开关 2 :反转编号为偶数的灯的状态(即 2, 4, ...
  • 开关 3 :反转编号为奇数的灯的状态(即 1, 3, ...
  • 开关 4 :反转编号为 j = 3k + 1 的灯的状态,其中 k = 0, 1, 2, ...(即 1, 4, 7, 10, ...

你必须 恰好 按压开关 presses 次。每次按压,你都需要从 4 个开关中选出一个来执行按压操作。

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

示例 1:

输入:n = 1, presses = 1
输出:2
解释:状态可以是:
- 按压开关 1 ,[关]
- 按压开关 2 ,[开]

示例 2:

输入:n = 2, presses = 1
输出:3
解释:状态可以是:
- 按压开关 1 ,[关, 关]
- 按压开关 2 ,[开, 关]
- 按压开关 3 ,[关, 开]

示例 3:

输入:n = 3, presses = 1
输出:4
解释:状态可以是:
- 按压开关 1 ,[关, 关, 关]
- 按压开关 2 ,[关, 开, 关]
- 按压开关 3 ,[开, 关, 开]
- 按压开关 4 ,[关, 开, 开]

 

提示:

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

方法一:归纳找规律

详细思路过程见官方题解,这里只做个人刷题记录,方便后续查询阅读

推荐题解

func flipLights(n int, presses int) int {
    if presses == 0 {
        return 1
    }
    if n == 1 {
        return 2
    } else if n == 2 {
        if presses == 1 {
            return 3
        }
        return 4
    }
    // n >= 3
    if presses == 1 {
        return 4
    } else if presses == 2 {
        return 7
    }
	return 8
}

复杂度分析

  • 时间复杂度:O(1)。
  • 空间复杂度:O(1)。

方法二:官方降低搜索空间

func flipLights(n int, presses int) int {
    seen := map[int]struct{}{}
    for i := 0; i < 1<<4; i++ {
        pressArr, sum := [4]int{}, 0
        for j := 0; j < 4; j++ {
            pressArr[j] = i >> j & 1
            sum += pressArr[j]
        }
        if sum%2 == presses%2 && sum <= presses {
            // 编号为 6k+1,受按钮 1,3,41,3,4 影响;
            status := pressArr[0] ^ pressArr[2] ^ pressArr[3]
            if n >= 2 {
                // 编号为 6k+2, 6k+6,受按钮 1,21,2 影响;
                status |= (pressArr[0] ^ pressArr[1]) << 1
            }
            if n >= 3 {
                // 编号为 6k+3, 6k+5,受按钮 1,31,3 影响;
                status |= (pressArr[0] ^ pressArr[2]) << 2
            }
            if n >= 4 {
                // 编号为 6k+4,受按钮 1,2,41,2,4 影响。
                status |= (pressArr[0] ^ pressArr[1] ^ pressArr[3]) << 3
            }
            seen[status] = struct{}{}
        }
    }
    return len(seen)
}

LeetCode题库地址