1 问题描述

Compute the Greatest Common Divisor of Two Integers using Sieve of Eratosthenes.

翻译:使用埃拉托色尼筛选法计算两个整数的最大公约数。(PS:最大公约数也称最大公因数,指两个或多个整数共有约数中最大的一个)


2 解决方案

2.1 埃拉托色尼筛选法原理简介

引用自百度百科:

埃拉托色尼筛选法(the Sieve of Eratosthenes)简称埃氏筛法,是古希腊数学家埃拉托色尼(Eratosthenes 274B.C.~194B.C.)提出的一种筛选法。 是针对自然数列中的自然数而实施的,用于求一定范围内的质数,它的容斥原理之完备性条件是p=H~。

具体求取质数的思想:

(1)先把1删除(现今数学界1既不是质数也不是合数)

(2)读取队列中当前最小的数2,然后把2的倍数删去

(3)读取队列中当前最小的数3,然后把3的倍数删去

(4)读取队列中当前最小的数5,然后把5的倍数删去

(5)如上所述直到需求的范围内所有的数均删除或读取

下面看一下执行上述步骤求不大于100的所有质数的一个示意图:

2.2 具体编码

本文求取两个数的最大公约数,采用质因数分解法:把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是这几个数的最大公约数

例如:求24和60的最大公约数,先分解质因数,得24=2×2×2×3,60=2×2×3×5,24与60的全部公有的质因数是2、2、3,它们的积是2×2×3=12,所以,(24,60)=12。

此处,第一步,先使用埃拉托色尼筛选法求取不大于数A的所有质数,然后从这些质数中选取A的所有质因数;第二步,依照第一步思想求取数B的所有质因数;第三步,求取数A和数B公共质因数;第四步,输出数A和数B的最大公约数。

具体代码如下:

package com.liuzhen.ex1;

import java.util.Scanner;

public class SieveOfEratosthenes {
//返回一维数组,数组中的元素为不大于n的所有质数
public static int[] getPrime(int n){
int[] result1 = new int[n]; //定义一个一维数组,并从第2个元素依次初始化为相应的自然数
for(int i = 2;i < n+1;i++){
result1[i-1] = i;
}
for(int i = 2;i < n;i++){
for(int j = i+1;j < n+1;j++){
if(j % i == 0) //如果j能够整除i,使result[j-1]等于0
result1[j-1] = 0;
}
}
int[] result2 = getNoneZero(result1); //除去result数组中所有0元素
return result2; //数组中非零元素即为不大于n的所有质数
} //返回一维数组,该数组的元素为参数数组中所有不为0的元素值
public static int[] getNoneZero(int[] A){
int len = 0;
for(int i = 0;i < A.length;i++){
if(A[i] != 0)
len = len+1;
}
int[] result = new int[len];
int k = 0;
for(int i = 0;i < A.length;i++){
if(A[i] != 0){
result[k] = A[i];
k++;
}
}
return result;
} //求取一个数n的所有质因数(eg:24=2×2×2×3,则result[] = {2,2,2,3})
public static int[] getNprime(int n){
int[] primes = getPrime(n);
int[] result; //最终返回结果集
int len = 0; //返回结果集数组长度,初始化为0
for(int i = 0;i < primes.length;i++){
int temp = n;
while(temp % primes[i] == 0){
temp = temp/primes[i];
len++;
}
}
result = new int[len];
int k = 0;
for(int i = 0;i < primes.length;i++){
int temp = n;
while(temp % primes[i] == 0){
temp = temp/primes[i];
result[k] = primes[i];
k++;
}
}
return result;
} //返回两个一维数组中所有共同元素
public static int[] getCommonPrime(int[] A , int[] B){
int[] result;
int lenA = A.length;
int lenB = B.length;
if(lenA < lenB){
result = new int[lenA];
for(int i = 0;i < lenA;i++){
int temp = A[i];
for(int j = 0;j < lenB;j++){
if(temp == B[j]){
result[i] = A[i];
B[j] = 0;
break;
}
}
}
}
else{
result = new int[lenB];
for(int i = 0;i < lenB;i++){
int temp = B[i];
for(int j = 0;j < lenA;j++){
if(temp == A[j]){
result[i] = B[i];
A[j] = 0;
break;
}
}
}
}
int[] result1 = getNoneZero(result);
return result1;
} //求取数A和B的最大公约数
public static void getMaxCommonDivisor(int A,int B){
int[] primesA = getNprime(A); //数A所有质因子
int[] primesB = getNprime(B); //数B所有质因子
int[] resultPrime = getCommonPrime(primesA,primesB); //数A和数B的公共质因数
int maxCommonDivisor = 1;
System.out.println(A+"和"+B+"的公共质因数为:");
for(int i = 0;i < resultPrime.length;i++){
maxCommonDivisor *= resultPrime[i];
System.out.print(resultPrime[i]+"\t");
}
System.out.println();
System.out.print(A+"和"+B+"的最大公约数为:"+maxCommonDivisor);
} public static void main(String[] args){
System.out.println("请输入数字A和数字B的值:");
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
getMaxCommonDivisor(a,b);
}
}

运行结果:

请输入数字A和数字B的值:
100 60
100和60的公共质因数为:
2 2 5
100和60的最大公约数为:20 请输入数字A和数字B的值:
60 48
60和48的公共质因数为:
2 2 3
60和48的最大公约数为:12 请输入数字A和数字B的值:
120 54
120和54的公共质因数为:
2 3
120和54的最大公约数为:6

算法笔记_012:埃拉托色尼筛选法(Java)的更多相关文章

  1. Java实现埃拉托色尼筛选法

    1 问题描述 Compute the Greatest Common Divisor of Two Integers using Sieve of Eratosthenes. 翻译:使用埃拉托色尼筛选 ...

  2. 使用埃拉托色尼筛选法(the Sieve of Eratosthenes)在一定范围内求素数及反素数(Emirp)

    Programming 1.3 In this problem, you'll be asked to find all the prime numbers from 1 to 1000. Prime ...

  3. 算法笔记_023:拓扑排序(Java)

    目录 1 问题描述 2 解决方案 2.1 基于减治法实现 2.2 基于深度优先查找实现 1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进 ...

  4. 算法笔记_014:合并排序(Java)

    1 问题描述 给定一组数据,使用合并排序得到这组数据的非降序排列. 2 解决方案 2.1 合并排序原理简介 引用自百度百科: 合并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Div ...

  5. 算法:时间复杂度+二分查找法(Java/Go/Python)实现

    导读 曾几何时学好数据结构与算法是我们从事计算机相关工作的基本前提,然而现在很多程序员从事的工作都是在用高级程序设计语言(如Java)开发业务代码,久而久之,对于数据结构和算法就变得有些陌生了,由于长 ...

  6. 算法笔记_228:信用卡号校验(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过Luhn算法来验证 ...

  7. 算法笔记_197:历届试题 带分数(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. ...

  8. 算法笔记_138:稳定婚姻问题(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 何为稳定婚姻问题? 有一个男士的集合Y = {m1,m2,m3...,mn}和一个女士的计划X = {n1,n2,n3,...,nn}.每一个男士有 ...

  9. 算法笔记_137:二分图的最大匹配(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 何为二分图的最大匹配问题? 引用自百度百科: 首先得说明一下何为匹配: 给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于 ...

随机推荐

  1. NOIP 2018 提高组初赛解题报告

    单项选择题: D 进制转换题,送分: D 计算机常识题,Python是解释运行的: B 常识题,1984年小平爷爷曰:“娃娃抓起”: A 数据结构常识题,带进去两个数据就可以选出来: D 历年真题没有 ...

  2. 关于那些oj链接

    luogu codeforces bzoj poj tyvj

  3. ACM -- 算法小结(六)逆波兰表达式

     逆波兰表达式 //问题描述:逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2+3的 //逆波兰表达式法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必 //用括号改 ...

  4. Codeforces Beta Round #8 C. Looking for Order 状压

    C. Looking for Order 题目连接: http://www.codeforces.com/contest/8/problem/C Description Girl Lena likes ...

  5. mybatis源码分析(7)-----缓存Cache(一级缓存,二级缓存)

    写在前面  MyBatis 提供查询缓存,用于减轻数据库压力,提高数据库性能. MyBatis缓存分为一级缓存和二级缓存. 通过对于Executor 的设计.也可以发现MyBatis的缓存机制(采用模 ...

  6. iOS程序的启动图片图标规范

     

  7. 用C++/CLI搭建C++和C#之间的桥梁(一)—— 简介

    C#和C++是非常相似的两种语言,然而我们却常常将其用于两种不同的地方,C#得益于其简洁的语法和丰富的类库,常用来构建业务系统.C++则具有底层API的访问能力和拔尖的执行效率,往往用于访问底层模块和 ...

  8. 反激 (Flyback) 控制器 -- LTC3803

    LTC3803 - 采用 ThinSOT 封装的恒定频率.电流模式.反激式 DC/DC 控制器 特点 VIN 和 VOUT 仅受限于外部元件 可调斜率补偿 内部软起动 200kHz 恒定频率操作 ±1 ...

  9. (转)媒体格式分析之flv -- 基于FFMPEG

    本来是应该先写一个媒体文件格式的简单讲解的,还没来得及写,以后再写.今天就先根据ffmpeg的flv.c的flv_demux这个结构体来讲解一下当前比较流行的媒体格式flv. FLV 是FLASH V ...

  10. 调整设置 Win7休眠文件“Hiberfil.sys”

    1. 显示并查看Hiberfil.sys文件