看到一道很有意思的编程题:大厅里有64盏灯,每盏灯都编了号码,分别为1-64。每盏灯都由一个开关来控制。(开关按一下,灯亮,再按一下灯灭。开关的编号与被控制的灯相同。)开始时,灯是全灭的。现在按照以下规则按动开关。 第一次,将所有的灯点亮。 第二次,将所有2的倍数的开关按一下。 第三次,将所有3 的倍数的开关按一下。以此类推。第N次,将所有N的倍数的开关按一下。 问第N次(N小于等于64)按完以后,大厅里还有几盏灯是亮的。提示可以用long型数字去做,很巧妙刚刚好表示64位,0或者1代表打开或者关闭。写了个实现和原作者的基本思路是一样的:
这个题目解答的巧妙之处就在于使用位操作来变换每一位的状态,非常好的思路。
- /**
- *
- * @author: yanxuxin
- * @date: 2010-3-13
- */
- public class LightSwiter {
- public static void main(String[] args) {
- long lights = switchLights(3);
- convert2Binary(lights);
- System.out.println();
- countOpenedLights(lights);
- }
- /**
- * 切换开关
- *
- * @param sequence
- * @return
- */
- public static long switchLights(int sequence) {
- long lights = 0l; //所有的都是关闭的状态,即64位均为0
- for (int i = 1; i <= sequence; i++) {
- for (int j = 1; j <= 64; j++) {
- if (j % i == 0) { //符合第n次的倍数
- long temp = 1l;
- temp = temp << (j - 1); //准备截取当前位
- if ((lights & temp) == 0) { //表明lights的当前位为0,即关闭状态
- lights = lights | temp; //不影响其他位数的情况下,改变lights的当前位的状态为1
- }
- else {
- temp = ~temp;
- lights = lights & temp; //不影响其他位数的情况下,改变lights的当前位的状态为0
- }
- }
- }
- }
- return lights;
- }
- /**
- * 统计点亮的灯数
- *
- * @param lights
- */
- public static void countOpenedLights(long lights) {
- int remains = 0;
- for (int k = 0; k < 64; k++) {
- long temp = 1l;
- temp = temp << k;
- temp = (lights & temp); //截取当前位判断
- if (temp != 0) {
- remains++;
- System.out.println("The " + (k + 1) + " light is opened.");
- }
- }
- System.out.println("Total " + remains + " lights are opened.");
- }
- /**
- * 转化成二进制的表达式显示
- *
- * @param number
- */
- public static void convert2Binary(long number) {
- long res = number / 2;
- long rem = number % 2;
- if (res != 0) {
- convert2Binary(res);
- }
- System.out.print(rem);
- }
- }
这个题目解答的巧妙之处就在于使用位操作来变换每一位的状态,非常好的思路。