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:

Flip all the lights.
Flip lights with even numbers.
Flip lights with odd numbers.
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].

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

 

优化点:

操作1是全转换,操作2和操作3是每两个转换一次,操作4是每三个转换一次。所以,以他们最小公倍数,6,不管怎么变化,k+0~k+5,k+6~k+11,k+12~k+17....(k < 6)每6个的状态是一样的。那么我们只用管前六个的可能,于是我们可以截取n的前一段,如果n大于6,那么对n取模 + 6即可。

 

用一个Integer的state来储存当前的状态,它的二进制表示中,0代表关灯,1代表开灯。四中变化形态,可以用位运算表示。

 

对state进行m次遍历,每遍都得到其分别进行四次变化后的结果,放在一个数组中。然后再对数组中的数字,进行第二次遍历。注意每次都排除相同的结果,避免重复运算。

 

class Solution {
    int num = 0;
    public int flipLights(int n, int m) {
        num = (n <= 6) ? n : (n % 6 + 6);
        Set<Integer>set = new HashSet<>(); // 排除相同状态
        Queue<Integer>queue = new ArrayDeque<>();
        queue.add((1 << n) - 1);
        for (int i = 0; i < m; i++) {
            int qSize = queue.size();
            set.clear();
            for (int j = 0; j < qSize; j++) {
                int top =  queue.remove();
                int[] res = new int[]{change1(top), change2(top), change3(top), change4(top)};
                for(int re: res) {
                    if (set.contains(re)) {
                        continue;
                    }
                    set.add(re);
                    queue.add(re);
                 }
            }
        }
        return queue.size();
    }

    int change1(int states){
        int t = (1 << num) - 1;
        return states ^ t;
    }

    int change2(int states){
        for (int i = 0; i < num; i = i + 2) {
            states ^= (1 << i);
        }
        return states;
    }

    int change3(int states){
        for (int i = 1; i < num; i = i + 2) {
            states ^= (1 << i);
        }
        return states;
    }

    int change4(int states){
        for (int i = 0; i < num; i = 3 * i + 1) {
            states ^= (1 << i);
        }
        return states;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值