Nth HCF of two number

江枫思渺然 提交于 2019-12-13 06:15:52

问题


I came across a coding quiz, given two no A and B find the nth HCF of the two no

for eg 16 , 8

HCF 8, 4, 2, 1 so 3rd HCF is 2

I solved like this

   1. X =  GCD(A,B)
   2. Find all factor of X
   3. Sort the factor in order 

But I want to know better approach

Thanks


回答1:


I think that the approach you have mentioned in description above is optimal except for the last step where you essentially do not need to sort the factors - you can simply generate them in increasing order.

You can read this interesting discussion on complexity of Euclid Algorithm which is the time complexity for your first step. Once GCD has been computed, finding all its factors will take O(sqrt(gcd)) time. You can generate them in increasing order as follows:

public ArrayList<Integer> factorize(int x) {
    ArrayList<Integer> factors_left = new ArrayList<>();
    ArrayList<Integer> factors_right = new ArrayList<>();
    for(int i=1; i<=(int)sqrt(x)+1; i++) {
        if(x%i==0) {
            factors_left.add(i);
            factors_right.add(x/i);
        }
    }
    ArrayList<Integer> allfactors = new ArrayList<>();
    for(int f: factors_left) {
        allfactors.add(f);
    }
    for(int i=factors_right.size()-1; i>=0; i--) {
        allfactors.add(factors_right.get(i));
    }
    return allfactors;
}

You can now simply traverse this list to find the desired factor.




回答2:


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]



回答3:


Like what Bhoot said but even better: find all the factors up to sqrt(x) in an increasing order, like Bhoot factors_left.

Now for nth HCF you just get X / factors_left[n].



来源:https://stackoverflow.com/questions/30368939/nth-hcf-of-two-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!