题目:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。
程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:
(1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。
(2)如果n <> k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步。
(3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。
网上这道题一搜就能找到,但是我看到的一个答案是这样的:
1 import java.util.Scanner;
2
3 public class lianxi04 {
4 public static void main(String[] args) {
5 Scanner s = new Scanner(System.in);
6 System.out.print("请键入一个正整数: ");
7 int n = s.nextInt();
8 int k = 2;
9 System.out.print(n + "=");
10 while (k <= n) {
11 if (k == n) {
12 System.out.println(n);
13 break;
14 } else if (n % k == 0) {
15 System.out.print(k + "*");
16 n = n / k;
17 } else {
18 k++;
19 }
20 }
21 }
22 }
这道题本身并没有什么难度,只要思路对了无论使用递归还是循环都可以解决。顺便说一下解题思路吧。接受一个输入的数字,就是被分解的数字(num),最小的质子数是2,然后num除以2,如果可以整除,2就是一个质因数,如果不可以2+1,再拿num除以进行整除判断。对所得的质因数输出。
这么写当然是可以得出正确答案的,但是想一想,这样的代码好吗?
以上代码有以下几点不好的地方:
1、 所有代码都写到了main中,这个是很不好的习惯,main方法一般就是做启动jvm用的不应该含有业务逻辑;
2、 请接受一个用户输入的数字从控制台接收,如果这个输入的数据是从一个界面或者网络来的,那这个程序不是得整体改动,获取处理数据应该是有一个方法封装。
3、 从控制台接收数据,获得的数据类型是int,但是以上程序在输入a这样的非int数据会抛异常,没有做异常处理,这个异常打印很不友好;
4、 分解质因数这个功能应该也算是一个算法,这个算法为了能够被可重复使用,需要进行封装;
5、 同理输出的方法也应该需要进行封装,题目虽然是输出道控制台,但是如果哪天需求变动,不是惨了。(该死的需求总是在变,大家应该都有体会);
6、 变量的命名:n,k谁能理解这个是什么意思啊。
下面是我对这道题解答的改进:
涉及五个类:
PrimeHandle:分解质因数处理类,核心算法
Input:获取输入数据的接口
ConsoleInput:从控制台输入数据的Input接口实现
Output:输出结果的接口
ConsoleOutput:从控制台输出结果的Output接口实现
Main:客户端程序,用于执行程序
上代码:
1 public class PrimeHandle {
2
3 //用于存放结果
4 private List<Integer> results = new ArrayList<Integer>();
5 //需要处理的数字
6 private int handleNum;
7 //最小的质子数
8 private static final int minPrime = 2;
9
10 PrimeHandle(int handleNum){
11 this.handleNum = handleNum;
12 }
13
14 //获得因子的方法
15 private void analyse(int num,int primeNum){
16 if(num<=primeNum){
17 results.add(num);
18 }else{
19 if(num%primeNum==0){
20 results.add(primeNum);
21 analyse(num/primeNum,minPrime);
22 }else{
23 primeNum++;
24 analyse(num,primeNum);
25 }
26 }
27 }
28
29 //获得结果
30 public String getResult(){
31 analyse(handleNum,minPrime);
32 StringBuilder resultStr = new StringBuilder();
33 for(int i:results){
34 resultStr.append(i+"*");
35 }
36 if(resultStr.length()>0){
37 return resultStr.substring(0,resultStr.length()-1);
38 }else{
39 return "";
40 }
41 }
42
43 }
44
45 public interface Input {
46 int getHandleNum();
47 }
48
49
50 public class ConsoleInput implements Input {
51
52 public int getHandleNum() {
53 int inputNum = 0;
54 Scanner scanner = new Scanner(System.in);
55 System.out.print("请输入一个数字:");
56 try{
57 inputNum = scanner.nextInt();
58 }catch(Exception e){
59 System.out.println("输入数据有误,请重新输入!");
60 inputNum = this.getHandleNum();
61 }
62 return inputNum;
63 }
64
65 }
66
67 public interface Output {
68 void out(String result);
69 }
70
71 public class ConsoleOutput implements Output {
72
73 public void out(String result) {
74 System.out.println("的因式分解为:"+result);
75 }
76
77 }
78
79 public class Main {
80 public static void main(String[] args) {
81 Input input = new ConsoleInput();
82 int handleNum = input.getHandleNum();
83 PrimeHandle handle = new PrimeHandle(handleNum);
84 String resultStr = handle.getResult();
85 Output output = new ConsoleOutput();
86 output.out(resultStr);
87
88 }
89 }
总结:
一道面试题,在那半个小时里你能想到这么多?
当然我肯定做不到这么完善,也没有机器调试代码,能写出个思路就差不多了。重点就是这个思路。面试题的结果的往往没有那么重要,但是这个过程和思路很重要。
很多人都说一直做增删改查真没有挑战性,太枯燥,没有意义,从这道题的思考我发现,再简单的事情你能把它做好都很困难。我的解答也许不是最好的,也许很繁琐,但是这个过程我体会很深。欢迎大家评论,发表一下自己的看法。