昨日去浦发面试,机试 的第三道题刚好不会。当时题意是什么都没看懂,就开做了。于是今天下来研究一波。
题目内容:
质因数分解。将一个数分解为多个因子相乘的形式,且每个因子都是质数。例如:
90=233*5
关联题目:
判断一个数是否为质数
丑数
尝试一
关键代码是unMake方法。
/*思路:需要一个arraylist result 来存质因子。从最小的质数(记做z)开始,让商(初识值为n)取除以它
* 1. 若余为0且商为1,结束
* 2. 若余为0商不为1,则result中添加质数z,用商(s)继续除以这个质数
* 3. 若余不为0,则z等于下一个质数。继续让s取去除以z
* */
private static void unMake(int n) {
//余数
int y = 0;
//商
int s = n;
//z表示第z个质数
int z = 0;
//一个数组来存值因子
ArrayList<Integer> result = new ArrayList<>();
while (true) {
if (s % get(z) == 0 && s / get(z) == 1) {
result.add(get(z));
break;
} else if (s % get(z) == 0) {
result.add(get(z));
s = s / get(z);
} else {
z++;
}
}
/*打印出result*/
System.out.print(n + "=");
for (int i = 0; i < result.size() - 1; ++i) {
System.out.print(result.get(i) + "*");
}
System.out.print(result.get(result.size() - 1));
}
//初始化一个数组来存储质数,初识大小为128,后期可以扩展容量
private static int[] nowZS = new int[128];
static {
/*i:表示第i质数;j用于从2开始遍历所有整数*/
for (int i = 0, j = 2; i < nowZS.length; ) {
if (isZS(j)) {
nowZS[i] = j;
i++;
j++;
} else {
j++;
}
}
}
/*
* 获取第i个质数,从0开始
* */
private static int get(int i) {
if (i >= nowZS.length) {
/*扩展nowZS。方法和static静态代码一样*/
int[] temp = new int[nowZS.length * 2];
int iterator = nowZS.length;
System.arraycopy(nowZS, 0, temp, 0, nowZS.length);
nowZS = temp;
for (int j = nowZS[iterator]; iterator < nowZS.length; ) {
if (isZS(j)) {
nowZS[iterator] = j;
iterator++;
j++;
} else {
j++;
}
}
}
return nowZS[i];
}
/*判断一个数是否为质数。最笨的方法用n去除2~n-1*/
private static boolean isZS(int n) {
//特殊情况处理
if (n == 1) {
return false;
}
if (n == 2) {
return true;
}
for (int i = 2; i < n - 1; ++i) {
if (n % i == 0) {
return false;
}
}
return true;
}
尝试二
判断一个数是否为质数还需要改进一下(因为我用的是最本的方法)。参考 判断一个数是否为质数/素数——从普通判断算法到高效判断算法思路
对于每个数n,其实并不需要从2判断到n-1,我们知道,一个数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),据此,上述代码中并不需要遍历到n-1,遍历到sqrt(n)即可,因为若sqrt(n)左侧找不到约数,那么右侧也一定找不到约数
我添加了一个isZS_2
方法,只要将尝试一中使用到isZS
的地方改为isZS_2
就行了
private static boolean isZS_2(int n){
//特殊情况处理
if (n <= 1) {
return false;
}
if (n == 2) {
return true;
}
double sq=Math.sqrt(n);
/*开方后直接为一个整数*/
if((sq-(int)sq)<1e-15){
return false;
}
for (int i = 2; i < sq; ++i) {
if (n % i == 0) {
return false;
}
}
return true;
}
总结
- 判断一个数是否为质数,有三种方法。分别是n除以2~n-1;n除以2~根号n;第三种方法有些不好理解,大于等于5的质数一定和6的倍数相邻(但是与6的倍数相邻的不一定是质数,如25)
- System.arrayCopy()方法前两个参数是src,紧接着后两个参数是dest,最后一个参数是copy长度。