【问题标题】:Nth HCF of two number两个数的第 N 个 HCF
【发布时间】:2015-05-21 08:55:03
【问题描述】:

我遇到了一个编码测验,给定两个 no A 和 B 找到两个 no 中的第 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 

但我想知道更好的方法

谢谢

【问题讨论】:

  • 这个问题不是真正的编程问题,它是一个数学问题,还有其他数学解决方案吗?如果没有,你可以在编程中做很多优化
  • 为什么是 HCF(16,8) 2 而不是 8?在维基百科上它说 hcf=gcd
  • 还有一种更简单的方法是测试每个数字 m
  • @LukaRahne 有点不清楚,但 HCF 是最高的公因数,而 2nd HCF 是第二高的公因数,表示仅次于第一个的第二高公因数。像 max[1, 2, 4, 3] 是 4 但第二个最大值是 3..

标签: algorithm greatest-common-divisor


【解决方案1】:

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

您可以阅读this interesting discussion 了解欧几里得算法的复杂性,这是您第一步的时间复杂度。 一旦计算了 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;
}

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

【讨论】:

    【解决方案2】:

    您可以从两个数的 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]
    

    【讨论】:

      【解决方案3】:

      就像 Bhoot 所说的,但更好: 按升序查找直到 sqrt(x) 的所有因子,例如 Bhoot factor_left。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-09-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-09
        • 1970-01-01
        相关资源
        最近更新 更多