用Java实现“带锁的门”算法
题目:带锁的门:
在走廊上有n个带锁的门,从1到n依次编号。最初所有的门都是关着的。我们从门前经过n次,每次都从1号门开始。在第i次经过时(i = 1,2,…, n)我们改变i的整数倍号锁的状态;如果门是关的,就打开它;如果门是打开的,就关上它。在最后一次经过后,哪些门是打开的,哪些门是关上的?有多少打开的门?
一、算法分析:
从1-n的所有门,要经过n次:
- 若k(k<=n)可分解为i*j(i!=j),则第k个门一定会有偶数次开关门的变化,则最后门的状态还是关闭。
如k = 18,可以分解成1x18,2x9,3x6,则第1次,2次,3次,6次,9次,18次经过第18号门,均会变化开关门的状态,原来是关门,经过偶数次变化,最终状态还是关门。 - 若k为完全平方数,如1、4、9、16,则第k个门只会有奇数次变化。
如k=4,只有1、2、4次经过会变化状态,故最后门是开的。
按照如上的分析,我们只需要判断1-n个门中有多少个完全平方数,即可确定开门的个数。
二、详细代码:
package Exercise2;
import java.util.ArrayList;
import java.util.Scanner;
public class theDoorWithLock {
public static void main(String[] args) {
System.out.println("请输入带锁的门的个数:");
int n = new Scanner(System.in).nextInt();
//sum统计开门的个数
int sum = 0;
//open存储开着的门的编号
ArrayList<Integer> open = new ArrayList<>();
for (int i = 1; i * i <= n; i++) {
open.add(i * i);
sum++;
}
//close存储关闭的门的编号
ArrayList<Integer> close = new ArrayList<>();
for (int i = 1; i <= n; i++) {
if (!open.contains(i))
close.add(i);
}
System.out.println("打开的门的编号为:");
for (Integer integer : open) {
System.out.print(integer + " ");
}
System.out.println("\r\n");
System.out.println("关着的门的编号为:");
for (Integer integer : close) {
System.out.print(integer + " ");
}
System.out.println("\r\n");
System.out.println("打开的门的个数为:" + sum);
}
}
三、运行结果: