解:
官方解法:
public class wsTest {
public static void main(String[] args) {
for (int m = 2; m < 1000; m++) {
int s = 0;
for (int i = 1; i < m; i++) {
if ((m % i) == 0) {
s += i;
}
}
if (s == m) {
System.out.print(m + " its factors are:");
for (int j = 1; j < m; j++) {
if ((m % j) == 0) {
System.out.print(j);
System.out.print(" ");
}
}
System.out.println();
}
}
}
}
官方解法非常直接,先遍历1000以内的所有数,如果该数能够和它的所有因子的和相等,则该数是完数,然后重新从2开始遍历获取所有因子,再打印。
但是个人认为随着数的增大,对每一个数,获取因子的操作执行了2次,每次判断是否是因子都是使用mod运算,且每次for循环的时间复杂度都是O(N),开销过大。
因此这里以空间换时间,对每次的遍历都先使用一个队列来存储当前的所有因子,如果遍历完发现是完数,将队列中的所有元素逐个打印即可。
不论该数是否是完数,队列最后都应该清空,否则会影响下一次的结果。
优化后的代码如下:
importjava.util.LinkedList;importjava.util.Queue;
public classTest {
public static voidmain(String[] args) {
final intLOWER_LIMIT = 2;final intUPPER_LIMIT = 1000;Queue q = newLinkedList<>();for(inti = LOWER_LIMIT;i <= UPPER_LIMIT;i++) {
ints = 0;for(intj = 1;j < i;j++) {
if(i % j == 0) {
s += j;q.offer(j);}
}
if(s == i) {
System.out.printf("%d是完数",s);System.out.print(",包括因子:");for(Integer one : q) System.out.print(one + " ");System.out.println();}
q.clear();}
}
}