题目: 输入两行分数, 求相加的最简分数。(具体看最下面的输入测试)
介绍:这是一道校招编程题,我在这里主要展示了两种方式破题,并且对这两种方法作了对比。第一种是求因数法,第二种方法是辗转相除法求两个数的最大公约数。下面是作者我实际破题代码:
版本一:求数的乘因数法
public static void T6() {
Scanner sc = new Scanner(System.in);
String numStr1 = sc.nextLine();
String numStr2 = sc.nextLine();
long[] arr1 = Arrays.stream(numStr1.split("/")).map(String::trim).mapToLong(Long::parseLong).toArray();
long[] arr2 = Arrays.stream(numStr2.split("/")).map(String::trim).mapToLong(Long::parseLong).toArray();
long a = arr1[0];
long b = arr1[1];
/* ----分隔符--- */
long c = arr2[0];
long d = arr2[1];
/**
*
* a c ad+ bc
* - + - = -------
* b d bd
*
*/
long m, n;
if (b == d) {
m = a + c;
n = b;
} else {
m = a * d + b * c;
n = b * d;
}
// 假设不会超过2^32次方, 如果要输入大值, 那么这里切换到64位去填充
int len = 32;
long[] arr = new long[len];
factors(n, arr, 0);
long next;
for (int i = 0; i < len; i++) {
next = arr[i];
if (next > 0) {
if (m % next == 0) {
m /= next;
n /= next;
}
} else
break;
}
System.out.println(m + " / " + n);
}
// 求质数因子法
public static void factors(long n, long[] arr, int m) {
if (n < 2)
return;
else if (n % 2 == 0) {
s(n, arr, m, 2);
} else {
for (long i = 3; i <= Math.sqrt(n); i += 2) {
if (n % i == 0) {
s(n, arr, m, i);
return;
}
}
arr[m] = n;
}
}
private static void s(long n, long[] arr, int m, long i) {
arr[m++] = i;
n /= i;
factors(n, arr, m);
}
测试:
// 输入测试:
/*
221/22
22/2
*/
/*
242/22
22/11
*/
T6();
上面代码关键部分:
public static void T6(long molecule, long denominator) {
// 假设不会超过2^32次方, 如果要输入大值, 那么这里切换到64位去填充
int len = 32;
long[] arr = new long[len];
factors(denominator, arr, 0);
long next;
for (int i = 0; i < len; i++) {
next = arr[i];
if (next > 0) {
if (molecule % next == 0) {
molecule /= next;
denominator /= next;
}
} else
break;
}
System.out.println(molecule + " / " + denominator);
}
关键代码测试:
T6(333, 9);
T6(236575676767876L, 2048);
版本二:辗转相除法求共因数
/**
* 辗转相除法求公除数
*
* @param molecule 分子
* @param denominator 分母
*/
public static long euclideanAlgorithm(long molecule, long denominator) {
long MOD = molecule % denominator;
if (MOD == 0) {
return denominator;
} else {
return euclideanAlgorithm(denominator, MOD);
}
}
/**
* 欧几里得算法: 辗转相除法求最大公约数
* 方法2
* 相比方法1, 非递归
*
* @param molecule
* @param denominator
* @return
*/
public static long euclideanAlgorithm1(long molecule, long denominator) {
long MOD;
do {
MOD = molecule % denominator;
molecule = denominator;
denominator = MOD;
} while (MOD > 0);
return molecule;
}
关键代码测试:
long divisor = divisionAlgorithm(236575676767876L, 2048);
System.out.println((x / divisor) + " / " + (y / divisor));
两种算法实战对比一:
对比二截图:
结果很明显,辗转相除法比求数的因子快的多。
如果你有什么问题,就请提出来吧,我看到了就会解答~ 同时我也谢谢大家大家的评论、点赞
作者留言:大家一起进步,冲啊!