題目描述
現給定任意正整數 n,請尋找並輸出最小的正整數 m(m>9),使得 m 的各位(個位、十位、百位 ... ...)之乘積等於n,若不存在則輸出 -1。
我的題解
暴力法
最原始的想法是遍歷,由於這個數一定不小於n,於是從n開始累加,然后轉化為字符數組,計算積,判斷
這個方法很傻,而且很難設置終止條件。
public int solution (int n) {
int a = n;
while(true){
char [] arr = Integer.toString(a).toCharArray();
int m=1;
for(char s:arr){
m*=s-48;
}
if(m>6*n)return -1;
else if (m==n) return a;
a++;
}
}
因式分解法
先把這個數徹底因式分解 n=n1*n2···nx
如果有個因子大於9,一定不存在m,why?
我們知道這個因子一定不是2-9的倍數,那么我們用個位數的乘積一定得不到這個數,故一定不存在m,直接返回-1
於是我們確定因式分解后因子 在2~9之間
我們使用數組來存放每個因子出現的次數。arr[i]代表i出現的次數
要使m最小,那么一定要使大的數字在低位,如9應該放在個位等低位。
我們從高位9到低位2掃描數組,找出所有的能夠組成較大的數的因子,用於填充低位。
最后得到的數一定是最小的。
public int solution (int n) {
int arr[] = new int[10]; //2~9用於存放因子個數
for(int i=2;;i++){//因式分解,從2~9判斷
if(n==1)break;//完成
if(i>9)return -1;//有大於9的因子,返回-1,結束
if(n%i==0){ // 可以整除
arr[i]++;//因子數量+1
n = n/i; //除去因子
i--; //徹底分解,再次判斷還能不能被i分解
}
}
String res = ""; //用一個字符串存放結果
for(int i=9;i>0;i--){ //從高位(9)開始掃描
while(arr[i]>0){ //先看是否存在單個這樣的數,如9
res=i+res;
arr[i]--;
}
//再看有沒有多個數積是i的
//由於不同的i 的因子組成不同,如8=2*2*2= 2*4,於是分情況討論
switch(i){
case 9:
while(arr[3]>=2){
res="9"+res;
arr[3]-=2;
}
break;
case 8:
while(arr[2]>=3){
res="8"+res;
arr[2]-=3;
}
while(arr[2]>0&&arr[4]>0){
res="8"+res;
arr[2]--;
arr[4]--;
}
break;
case 6:
while(arr[2]>0&&arr[3]>0){
res="6"+res;
arr[2]--;
arr[3]--;
}
break;
case 4:
while(arr[2]>=2){
res="4"+res;
arr[2]-=2;
}
//7、5、3是素數,不能被非1因子分解
}
}
return Integer.valueOf(res);//返回結果
}