You can derive your list of common factors from the prime factors of the hcf of the two numbers.
Here's a demo using code I had lying around. I use an implementation of the Extended Euclidean algorithm for the GCD just because I had one available. It's not necessarily the fastest solution.
/**
* Prime factors of the number - not the most efficient but it works.
*
* @param n - The number to factorise.
* @return - List of all prime factors of n.
*/
public static List<Long> primeFactors(long n) {
return primeFactors(n, false);
}
/**
* Prime factors of the number - not the most efficient but it works.
*
* @param n - The number to factorise.
* @param unique - Want only unique factors.
* @return - List of all prime factors of n.
*/
public static List<Long> primeFactors(long n, boolean unique) {
Collection<Long> factors;
if (unique) {
factors = new HashSet<>();
} else {
factors = new ArrayList<>();
}
for (long i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
if (n > 1) {
factors.add(n);
}
return new ArrayList<>(factors);
}
/**
* Extended Euclidean algorithm to find the GCD of a and b.
*
* We assume here that a and b are non-negative (and not both zero).
*
* This function also will return numbers j and k such that d = j*a + k*b where d is the GCD of a and b.
*/
public static int[] extendedEuclid(int a, int b) {
int[] ans = new int[3];
int q;
// If b = 0, then we're done...
if (b == 0) {
// All over.
ans[0] = a;
ans[1] = 1;
ans[2] = 0;
} else {
// Otherwise, make a recursive function call
q = a / b;
ans = extendedEuclid(b, a % b);
int temp = ans[1] - ans[2] * q;
ans[1] = ans[2];
ans[2] = temp;
}
return ans;
}
/**
* Common factors of the GCD of the two numbers.
*
* @param a - First number.
* @param b - Second number.
* @return - List of common factors.
*/
public static List<Long> cfs(int a, int b) {
return primeFactors(extendedEuclid(a, b)[0]);
}
private static void test(int a, int b) {
// Get the GCD.
int[] ee = extendedEuclid(a, b);
System.out.println("eEu(" + a + "," + b + ") = " + Arrays.toString(ee));
// Get common factors.
List<Long> cfs = cfs(a, b);
System.out.println("cfs(" + a + "," + b + ") = " + cfs);
// Build your list of what you call HCFs.
List<Long> hcfs = new ArrayList<>();
// Start at the GCD.
long hcf = ee[0];
for (Long l : cfs) {
// Record that factor.
hcfs.add(hcf);
// Remove this prime factor from it.
hcf /= l;
// Obviously you could stop when you have your nth one.
}
// Also add `1`
hcfs.add(1l);
System.out.println("hcfs(" + a + "," + b + ") = " + hcfs);
}
public void test() {
test(16, 8);
test(144, 72);
}
This prints:
eEu(16,8) = [8, 0, 1]
cfs(16,8) = [2, 2, 2]
hcfs(16,8) = [8, 4, 2, 1]
eEu(144,72) = [72, 0, 1]
cfs(144,72) = [2, 2, 2, 3, 3]
hcfs(144,72) = [72, 36, 18, 9, 3, 1]