題目:將一個正整數分解質因數。例如:輸入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 }
總結:
一道面試題,在那半個小時里你能想到這么多?
當然我肯定做不到這么完善,也沒有機器調試代碼,能寫出個思路就差不多了。重點就是這個思路。面試題的結果的往往沒有那么重要,但是這個過程和思路很重要。
很多人都說一直做增刪改查真沒有挑戰性,太枯燥,沒有意義,從這道題的思考我發現,再簡單的事情你能把它做好都很困難。我的解答也許不是最好的,也許很繁瑣,但是這個過程我體會很深。歡迎大家評論,發表一下自己的看法。