思路

这道题第一次见到的时候发现解法可以很暴力。

Java版本代码

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
    public static List<Integer> revert(int num) {
        List<Integer> list = new ArrayList<>();
        for (int i = 2; i <= num; i++) {
            if (num % i == 0) {
                list.add(i);
                num /= i;
                i--;
            }
        }
        if (list.isEmpty()) {
            list.add(num);
        }
        return list;
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int a = in.nextInt();
            List<Integer> list = revert(a);
            list.forEach(integer -> System.out.print(integer + " "));
        }
    }
}

就是从2开始反复的去除输入的数字,发现可以整除就输出。这种解法的好处就是简单,但是坏处也很明显,就是特别慢,我的这段代码的执行时间已经达到了3259ms,基本快超时了。

继续审视这道题,发现这其实是判断素数的一个变种。

我们知道,如果一个数不是素数,那么这个数字一定会有至少一个因子小于sqrt(number),另外会有一个因子大于sqrt(number),根据这个原理改造一下代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static List<Integer> revert(int num) {
        List<Integer> list = new ArrayList<>();
        int end = (int) Math.sqrt(num);
        for (int i = 2; i <= end; i++) {
            while (num % i == 0) {
                list.add(i);
                num /= i;
            }
            if (num == 1) {
                break;
            }
        }
        // 这一句负责找到那个大于num平方根的因子
        if (num != 1) {
            list.add(num);
        }
        if (list.isEmpty()) {
            list.add(num);
        }
        return list;
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int a = in.nextInt();
            List<Integer> list = revert(a);
            list.forEach(integer -> System.out.print(integer + " "));
        }
    }
}

这一段代码的执行时间就只有185ms了。

另外还是要感叹C语言的效率,同样的算法,执行只需要3ms:

#include <stdio.h>
#include <math.h>

int main(void)
{
    int num;
    scanf("%d", &num);
    int end = (int) sqrt(num);
    for (int i = 2; i <= end; i++)
    {
        while (num % i == 0)
        {
            printf("%d ", i);
            num /= i;
        }
        if (num == 1)
        {
            break;
        }
    }
    if (num != 1) 
    {
        printf("%d ", num);
    }
    return 0;
}