求n个数的gcd最快的方法是什么?

发布于 2024-10-16 02:34:03 字数 28 浏览 4 评论 0原文

计算n个数字的最大公约数的最快方法是什么?

what is the fastest way to compute the greatest common divisor of n numbers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

浅黛梨妆こ 2024-10-23 02:34:03

不使用递归:

int result = numbers[0];
for(int i = 1; i < numbers.length; i++){
    result = gcd(result, numbers[i]);
}
return result;

对于非常大的数组,使用 fork-join 模式可能会更快,在该模式中,您可以分割数组并并行计算 gcd。这是一些伪代码:

int calculateGCD(int[] numbers){
    if(numbers.length <= 2){
        return gcd(numbers);    
    }
    else {
        INVOKE-IN-PARALLEL {
            left = calculateGCD(extractLeftHalf(numbers));
            right = calculateGCD(extractRightHalf(numbers));
        }
        return gcd(left,right);
    }
}

Without recursion:

int result = numbers[0];
for(int i = 1; i < numbers.length; i++){
    result = gcd(result, numbers[i]);
}
return result;

For very large arrays, it might be faster to use the fork-join pattern, where you split your array and calculate gcds in parallel. Here is some pseudocode:

int calculateGCD(int[] numbers){
    if(numbers.length <= 2){
        return gcd(numbers);    
    }
    else {
        INVOKE-IN-PARALLEL {
            left = calculateGCD(extractLeftHalf(numbers));
            right = calculateGCD(extractRightHalf(numbers));
        }
        return gcd(left,right);
    }
}
小矜持 2024-10-23 02:34:03

您可能需要先对数字进行排序,然后从最小的两个数字开始递归计算 gcd。

You may want to sort the numbers first and compute the gcd recursively starting from the smallest two numbers.

咿呀咿呀哟 2024-10-23 02:34:03

C++17

我编写了这个函数,通过使用 C++ 内置的 __gcd(int a, int b) 函数来计算 n 个数字的 gcd。

int gcd(vector<int> vec, int vsize)
{
    int gcd = vec[0];
    for (int i = 1; i < vsize; i++)
    {
        gcd = __gcd(gcd, vec[i]);
    }
    return gcd;
}

要了解有关此功能的更多信息,请访问此链接

另请参阅 Dijkstra 的 GCD 算法以下链接。它无需分割即可工作。所以它可能会稍微快一些(如果我错了,请纠正我。)

C++17

I have written this function for calculating gcd of n numbers by using C++'s inbuilt __gcd(int a, int b) function.

int gcd(vector<int> vec, int vsize)
{
    int gcd = vec[0];
    for (int i = 1; i < vsize; i++)
    {
        gcd = __gcd(gcd, vec[i]);
    }
    return gcd;
}

To know more about this function visit this link .

Also refer to Dijkstra's GCD algorithm from the following link. It works without division. So it could be slightly faster (Please correct me if I am wrong.)

随心而道 2024-10-23 02:34:03

您应该使用 Lehmer 的 GCD 算法

You should use Lehmer's GCD algorithm.

ζ澈沫 2024-10-23 02:34:03

下面通过减法使用欧几里得算法怎么样:

function getGCD(arr){
    let min = Math.min(...arr); 
    let max= Math.max(...arr);
    if(min==max){
        return min;
    }else{
         for(let i in arr){
            if(arr[i]>min){
                arr[i]=arr[i]-min;
            }
        }
        return getGCD(arr);
    }
   
}

console.log(getGCD([2,3,4,5,6]))

上述实现需要 O(n^2) 时间。有改进可以实现,但我没有尝试这些出n个数。

How about the following using Euclidean algorithm by subtraction:

function getGCD(arr){
    let min = Math.min(...arr); 
    let max= Math.max(...arr);
    if(min==max){
        return min;
    }else{
         for(let i in arr){
            if(arr[i]>min){
                arr[i]=arr[i]-min;
            }
        }
        return getGCD(arr);
    }
   
}

console.log(getGCD([2,3,4,5,6]))

The above implementation takes O(n^2) time. There are improvements that can be implemented but I didn't get around trying these out for n numbers.

沉睡月亮 2024-10-23 02:34:03

如果您有很多数字,因式分解实际上可能会更快。

//Java
int[] array = {60, 90, 45};
int gcd = 1;
outer: for (int d = 2; true; d += 1 + (d % 2)) {
    boolean any = false;
    do {
        boolean all = true;
        any = false;
        boolean ready = true;
        for (int i = 0; i < array.length; i++) {
            ready &= (array[i] == 1);
            if (array[i] % d == 0) {
                any = true;
                array[i] /= d;
            } else all = false;
        }
        if (all) gcd *= d;
        if (ready) break outer;
    } while (any);
}
System.out.println(gcd);

(适用于一些示例,但未经真正测试)

If you have a lot of small numbers, factorization may be actually faster.

//Java
int[] array = {60, 90, 45};
int gcd = 1;
outer: for (int d = 2; true; d += 1 + (d % 2)) {
    boolean any = false;
    do {
        boolean all = true;
        any = false;
        boolean ready = true;
        for (int i = 0; i < array.length; i++) {
            ready &= (array[i] == 1);
            if (array[i] % d == 0) {
                any = true;
                array[i] /= d;
            } else all = false;
        }
        if (all) gcd *= d;
        if (ready) break outer;
    } while (any);
}
System.out.println(gcd);

(works for some examples, but not really tested)

指尖凝香 2024-10-23 02:34:03

使用欧几里德算法

function gcd(a, b)
while b ≠ 0
   t := b; 
   b := a mod b; 
   a := t; 
return a;

将其应用于前两个数字,然后应用第三个数字的结果,依此类推...:

read(a);
read(b);

result := gcd(a, b);
i := 3;
while(i <= n){
    read(a)
    result := gcd(result, a);
}
print(result);

Use the Euclidean algorithm :

function gcd(a, b)
while b ≠ 0
   t := b; 
   b := a mod b; 
   a := t; 
return a;

You apply it for the first two numbers, then the result with the third number, etc... :

read(a);
read(b);

result := gcd(a, b);
i := 3;
while(i <= n){
    read(a)
    result := gcd(result, a);
}
print(result);
爱人如己 2024-10-23 02:34:03

下面是使用数组查找 N 个数字的 HCF 的 C 程序的源代码。

#include<stdio.h>

int main()
{
    int n,i,gcd;
    printf("Enter how many no.s u want to find gcd : ");
    scanf("%d",&n);
    int arr[n];
    printf("\nEnter your numbers below :- \n ");
    for(i=0;i<n;i++)
    {
        printf("\nEnter your %d number = ",i+1);
        scanf("%d",&arr[i]);
    }
    gcd=arr[0];
    int j=1;
    while(j<n)
    {
       if(arr[j]%gcd==0)
       {
           j++;
       }
       else
       {
           gcd=arr[j]%gcd;
           i++;
       }
    }
    printf("\nGCD of k no.s = %d ",gcd);
    return 0;
}

有关更多信息,请参阅此网站以获取进一步说明…………

Here below is the source code of the C program to find HCF of N numbers using Arrays.

#include<stdio.h>

int main()
{
    int n,i,gcd;
    printf("Enter how many no.s u want to find gcd : ");
    scanf("%d",&n);
    int arr[n];
    printf("\nEnter your numbers below :- \n ");
    for(i=0;i<n;i++)
    {
        printf("\nEnter your %d number = ",i+1);
        scanf("%d",&arr[i]);
    }
    gcd=arr[0];
    int j=1;
    while(j<n)
    {
       if(arr[j]%gcd==0)
       {
           j++;
       }
       else
       {
           gcd=arr[j]%gcd;
           i++;
       }
    }
    printf("\nGCD of k no.s = %d ",gcd);
    return 0;
}

For more refer to this website for further clarification.......

清风无影 2024-10-23 02:34:03

您可以使用分而治之的方法。要计算 gcdN([]),请将列表分为前半部分和后半部分。如果每个列表只有一个数字。您可以使用 gcd2(n1, n2) 进行计算。

我刚刚写了一个快速示例代码。 (假设列表中的所有 num 都是正整数)

def gcdN(nums):
    n = len(nums)
    if n == 0: return "ERROR"
    if n == 1: return nums[0]
    if n >= 2: return gcd2(gcdN(nums[:n//2]), gcdN(nums[n//2:]))

def gcd2(n1, n2):
    for num in xrange(min(n1, n2), 0, -1):
        if n1 % num == 0 and n2 % num == 0:
            return num

You can use divide and conquer. To calculate gcdN([]), you divide the list into first half and second half. if it only has one num for each list. you calculate using gcd2(n1, n2).

I just wrote a quick sample code. (assuming all num in the list are positive Ints)

def gcdN(nums):
    n = len(nums)
    if n == 0: return "ERROR"
    if n == 1: return nums[0]
    if n >= 2: return gcd2(gcdN(nums[:n//2]), gcdN(nums[n//2:]))

def gcd2(n1, n2):
    for num in xrange(min(n1, n2), 0, -1):
        if n1 % num == 0 and n2 % num == 0:
            return num
孤独陪着我 2024-10-23 02:34:03

这是一个 gcd 方法,它使用 gcd(a, b, c) = gcd(a, gcd(b, c)) 的属性。
它使用 BigInteger 的 gcd 方法,因为它已经过优化。

public static BigInteger gcd(BigInteger[] parts){
    BigInteger gcd = parts[0];
    for(int i = 1; i < parts.length; i++)
        gcd = parts[i].gcd(gcd);
    return gcd;
}

Here's a gcd method that uses the property that gcd(a, b, c) = gcd(a, gcd(b, c)).
It uses BigInteger's gcd method since it is already optimized.

public static BigInteger gcd(BigInteger[] parts){
    BigInteger gcd = parts[0];
    for(int i = 1; i < parts.length; i++)
        gcd = parts[i].gcd(gcd);
    return gcd;
}
迷你仙 2024-10-23 02:34:03
//Recursive solution to get the GCD of Two Numbers

long long int gcd(long long int a,long long int b)<br>
{
   return b==0 ? a : gcd(b,a%b);
}
int main(){
  long long int a,b;
  cin>>a>>b;
  if(a>b) cout<<gcd(a,b);
  else cout<<gcd(b,a);
return 0;
}
//Recursive solution to get the GCD of Two Numbers

long long int gcd(long long int a,long long int b)<br>
{
   return b==0 ? a : gcd(b,a%b);
}
int main(){
  long long int a,b;
  cin>>a>>b;
  if(a>b) cout<<gcd(a,b);
  else cout<<gcd(b,a);
return 0;
}
在风中等你 2024-10-23 02:34:03
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

class GCDArray{
    public static int [] extractLeftHalf(int [] numbers)
    {
        int l =numbers.length/2;
        int arr[] = Arrays.copyOf(numbers, l+1);
        return arr;
    }

    public static int [] extractRightHalf(int [] numbers)
    {
        int l =numbers.length/2;
        int arr[] = Arrays.copyOfRange(numbers,l+1, numbers.length);
        return arr;
    }

    public static int gcd(int[] numbers)
    {
        if(numbers.length==1)
            return numbers[0];
        else {
            int x = numbers[0];
            int y = numbers[1];
            while(y%x!=0)
            {
                int rem = y%x;
                y = x;
                x = rem;
            }
            return x;
        }
    }
    public static int gcd(int x,int y)
    {
            while(y%x!=0)
            {
                int rem = y%x;
                y = x;
                x = rem;
            }
            return x;

    }
    public static int calculateGCD(int[] numbers){
        if(numbers.length <= 2){
            return gcd(numbers);    
        }
        else {

                    int left = calculateGCD(extractLeftHalf(numbers));
                    int right = calculateGCD(extractRightHalf(numbers));

            return gcd(left,right);
        }
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int arr[] = new int[n];
        for(int i=0;i<n;i++){
            arr[i]=sc.nextInt();
        }
        System.out.println(calculateGCD(arr));
    }
}

**

上面是java工作代码.....其伪代码是
https://stackoverflow.com/users/7412/dogbane

已经提到过

**

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

class GCDArray{
    public static int [] extractLeftHalf(int [] numbers)
    {
        int l =numbers.length/2;
        int arr[] = Arrays.copyOf(numbers, l+1);
        return arr;
    }

    public static int [] extractRightHalf(int [] numbers)
    {
        int l =numbers.length/2;
        int arr[] = Arrays.copyOfRange(numbers,l+1, numbers.length);
        return arr;
    }

    public static int gcd(int[] numbers)
    {
        if(numbers.length==1)
            return numbers[0];
        else {
            int x = numbers[0];
            int y = numbers[1];
            while(y%x!=0)
            {
                int rem = y%x;
                y = x;
                x = rem;
            }
            return x;
        }
    }
    public static int gcd(int x,int y)
    {
            while(y%x!=0)
            {
                int rem = y%x;
                y = x;
                x = rem;
            }
            return x;

    }
    public static int calculateGCD(int[] numbers){
        if(numbers.length <= 2){
            return gcd(numbers);    
        }
        else {

                    int left = calculateGCD(extractLeftHalf(numbers));
                    int right = calculateGCD(extractRightHalf(numbers));

            return gcd(left,right);
        }
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int arr[] = new int[n];
        for(int i=0;i<n;i++){
            arr[i]=sc.nextInt();
        }
        System.out.println(calculateGCD(arr));
    }
}

**

Above is the java working code ..... the pseudo code of which is
already mention by https://stackoverflow.com/users/7412/dogbane

**

老娘不死你永远是小三 2024-10-23 02:34:03

一种适用于任意位数的递归 JavaScript (ES6) 单行代码。

const gcd = (a, b, ...c) => b ? gcd(b, a % b, ...c) : c.length ? gcd(a, ...c) : Math.abs(a);

A recursive JavaScript (ES6) one-liner for any number of digits.

const gcd = (a, b, ...c) => b ? gcd(b, a % b, ...c) : c.length ? gcd(a, ...c) : Math.abs(a);
甜是你 2024-10-23 02:34:03

这就是我在 Javascript 中想到的。

function calculateGCD(arrSize, arr) {
    if(!arrSize)
        return 0;
    var n = Math.min(...arr);
    for (let i = n; i > 0; i--) {
        let j = 0;
        while(j < arrSize) {
            if(arr[j] % i === 0) {
                j++;
            }else {
                break;
            }
            if(j === arrSize) {
                return i;
            }
        }
    }
}

console.log(generalizedGCD(4, [2, 6, 4, 8]));
// Output => 2

This is what comes off the top of my head in Javascript.

function calculateGCD(arrSize, arr) {
    if(!arrSize)
        return 0;
    var n = Math.min(...arr);
    for (let i = n; i > 0; i--) {
        let j = 0;
        while(j < arrSize) {
            if(arr[j] % i === 0) {
                j++;
            }else {
                break;
            }
            if(j === arrSize) {
                return i;
            }
        }
    }
}

console.log(generalizedGCD(4, [2, 6, 4, 8]));
// Output => 2
雨后彩虹 2024-10-23 02:34:03

这就是我一直在寻找的答案。
找到n个数的gcd的最佳方法确实是使用递归。即gcd(a,b,c)=gcd(gcd(a,b),c)。但当我这样做时,我在某些程序中遇到了超时。

这里需要的优化是应该使用快速矩阵乘法算法来解决递归。

Here was the answer I was looking for.
The best way to find the gcd of n numbers is indeed using recursion.ie gcd(a,b,c)=gcd(gcd(a,b),c). But I was getting timeouts in certain programs when I did this.

The optimization that was needed here was that the recursion should be solved using fast matrix multiplication algorithm.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文