LeetCode/灯泡开关

1. 灯泡开关I

初始时有 n 个灯泡处于关闭状态,第i轮切换i的倍数位置的开关,直到第n轮切换位置n的灯泡开关,返回n轮后灯泡亮着个数

实际上就是求进行奇数次操作灯泡个数,对第k个灯泡进行操作的轮次为其约数,约数一般成对存在,除非为完全平方数
原问题转换为求1~n的完全平方数个数

return (int)pow(n,0.5);

2. 灯泡开关II

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

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

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

已知开关1影响所有灯泡,编号为6k+1受开关3,4影响,编号6k+4受开关2,4影响
编号6k+2,6k+6受开关2影响, 编号6k+3,6k+5受开关3影响
实际上前4个灯泡的状态,已经决定了后面所有灯泡状态

接下来遍历所有开关状态(16种),求解对应四个灯泡状态即可

class Solution {
public:
    int flipLights(int n, int presses) {
        unordered_set<int> s;
        for (int i = 0; i < 1 << 4; i++) {//遍历4位的全排列,即16种开关状态
            vector<int> pressArr(4);
            for (int j = 0; j < 4; j++) //将开关状态4位二进制转化成数组形式,便于后续计算
                pressArr[j] = (i >> j) & 1;
            int sum = accumulate(pressArr.begin(), pressArr.end(), 0);
            if (sum % 2 == presses % 2 && sum <= presses) {//开关状态奇偶性应该与操作数一致
                int status = pressArr[0] ^ pressArr[1] ^ pressArr[3];//灯泡1状态依赖
                if (n >= 2) 
                    status |= (pressArr[0] ^ pressArr[1]) << 1;//灯泡2状态依赖,并移到第二位
                if (n >= 3) 
                    status |= (pressArr[0] ^ pressArr[2]) << 2;//灯泡3状态依赖,并移到第三位
                if (n >= 4) 
                    status |= (pressArr[0] ^ pressArr[1] ^ pressArr[3]) << 3;//灯泡4状态依赖
                s.emplace(status);//用4位二进制数表示灯泡状态
            }
        }
        return s.size();
    }
};
posted @ 2022-09-15 01:19  失控D大白兔  阅读(68)  评论(0编辑  收藏  举报