Nth HCF的两个数字

时间:2015-05-21 08:55:03

标签: algorithm greatest-common-divisor

我遇到了一个编码测验,给出两个没有A和B找到两个没有的第n个HCF

例如16,8

HCF 8,4,2,1  所以第三个HCF是2

我这样解决了

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

但我想知道更好的方法

由于

3 个答案:

答案 0 :(得分:2)

我认为您在上面描述中提到的方法是最优的,除了您基本上不需要对因子进行排序的最后一步 - 您可以简单地按递增顺序生成它们。

您可以阅读this interesting discussion关于Euclid算法的复杂性,这是您第一步的时间复杂度。 一旦计算出GCD,找到所有因子将花费O(sqrt(gcd))时间。您可以按如下顺序生成它们:

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;
}

您现在可以简单地遍历此列表以找到所需的因子。

答案 1 :(得分:1)

您可以从两个数字的hcf的素因子中推导出您的公因子列表。

这是一个使用我躺在身边的代码的演示。我为GCD使用了Extended Euclidean algorithm的实现,因为我有一个可用的。它不一定是最快的解决方案。

/**
 * 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);
}

打印:

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]

答案 2 :(得分:0)

就像Bhoot所说的那样,但更好: 以递增的顺序查找最多为sqrt(x)的所有因子,如Bhoot factors_left。

现在,对于第n个HCF,您只需获得X / factors_left [n]。