算法--100盏灯问题

题目

一间屋子里有100盏灯排成一行,按从左至右的顺序编号1、2、3、4、5…99、100,每盏灯都有一个开关,开始全部都关着,现有100个学生,

  • 1、第1个学生按了1的倍数的灯,也就说被按灯的编号为:1、2、3、4、5、6、7、8…99、100
  • 2、第2个学生按了2的倍数的灯,也就说被按灯的编号为:2、4、6、8、10…98、100
  • 3、第3个学生按了3的倍数的灯,也就说被按灯的编号为:3、6、9、12…99
  • 4、以此类推…
  • 100、第100个学生把100的倍数灯,,也就说被按灯的编号为:100

把结束之后还亮着的灯列出来。

解法一

Go:

ans := make(map[int]bool, 101)
for i := 1; i <= 100; i++ {
	for j := i; j <= 100; j = j + i {
		ans[j] = !ans[j]
	}
}
var res []int
for i := 1; i <= 101; i++ {
	if ans[i] {
		res = append(res, i)
	}
}
return res

PHP:

$ans = [];
for ($i = 1; $i <= 100; $i++) {
    $j = $i;
    while ($j <= 100) {
        if (isset($ans[$j])) {
            if ($ans[$j] == 1 ) {
                unset($ans[$j]);
            } else {
                $ans[$j] = 1;
            }
        } else {
            $ans[$j] = 1;
        }
        $j += $i;
    }
}
$ans = array_keys($ans);
return $ans;

解法二

思路:
其实就是求1-100中,完全平方数有几个?为什么是求1-100中的完全平方数,下面详解。

因为灯开始都是关着的,所以某一个灯被按了奇数次,灯就是开的。现在我们只要得到被按奇数次的灯的编号即可得到结果。

我们通过画图模拟这一场景,只模拟10盏灯的情况。

image

 

总结一下:

1号灯:被按了1次,仅被第1个学生按了
2号灯:被按了2次,被第1和第2个学生按了
3号灯:被按了2次,被第1和第3个学生按了
4号灯:被按了3次,被第1、第2和第4个学生按了
5号灯:被按了2次,被第1和第5个学生按了
6号灯:被按了4次,被第1、第2、第3和第6个学生按了
7号灯:被按了2次,被第1和第7个学生按了
8号灯:被按了4次,被第1、第2、第4、和第8个学生按了
9号灯:被按了3次,被第1、第3和第9个学生按了
10号灯:被按了2次,被第1和第10个学生按了
上面我们得出,灯只要被按了奇数次,灯就是开的,所以1、4、9号灯是开的,这跟画图模拟结果一致。

下面分析一下:

1号灯是开的,1号学生按了
4号灯是开的,分别由1、2、4号学生按了;
依次来推…
8号灯是关的,分别由1、2、4、8号学生按了;
9号灯是开的,分别由1、3、9号学生按了;
基于上面的结果我们猜测:每盏灯按的次数与灯的编号所含约数的个数有关。 比如4号灯,4的约数为 1、2、4,所以4号灯被按了3次。比如8号灯,8的约数是 1、2、4、8,所以8号灯被按了4次。9号灯同理。所以我们只要找到1~100这些数中约数个数是奇数的数。

什么是约数,不知道的百度。那1~100中哪些数的约数的个数是奇数?一般来说,一个数的约数都是成对出现的,所以一般一个数的约数的个数都是偶数,如上述8的约数 1、2、4、8。
但是也有例外:

如9的约数有 1、3、9
如16的约数有 1、2、4、8、16
如36的约数有 1、2、3、4、6、9、12、18、36
上面举例9、16、36的约数的个数都是奇数,为什么?因为有一个约数相等了,如 9 的约数有 1、3、3、9,但是3是相等的,所以去掉一个。同理16、36约数的个数是奇数的原因都是如此。

所以我们得出结论,约数个数为奇数的数就是一个完全平方数。

这个结论与解法一相同。综上我们得出,100盏灯的问题其实就是求1-100中,完全平方数有几个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值