Essayez d'implémenter le tamis Eratostenes en utilisant la bibliothèque standard de Java

introduction

Je développe généralement des logiciels packagés, mais j'ai récemment commencé un pro de la concurrence. C'était complètement différent de la façon habituelle d'écrire du code, donc j'étais très confus (je résolvais le problème en pensant que je ne serais pas tué si j'écrivais un tel code), et je me demandais ce qui se passerait si j'implémentais cela comme d'habitude.

Dans un tel cas, le tamis [Java] Eratostenes de @ nkojima trouve le nombre premier et le tamis [Java] Eratostenes trouve le nombre premier (partie 2) , j'ai pensé que ce serait un bon sujet, j'ai donc essayé d'améliorer la lisibilité en utilisant la bibliothèque standard.

À ce stade, j'essaierai d'utiliser correctement la collection.

code

[Java] Recherche de nombres premiers avec un tamis d'erratostines (2), reportez-vous à ʻArrayList, HashSet`, ʻArrayList <Boolean Je l'ai changé en> ʻet je l'ai implémenté.

ListImplement.java


package practise.algorithm.eratosthenes.qiita;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class ListImplement {
	private static final int MIN_PRIME_NUMBER = 2;

	public static void main(String[] args) {
		new ListImplement().execute();
	}

	private void execute() {
		Scanner sc = new Scanner(System.in);
		int maxNumber = sc.nextInt();

		List<Integer> primeNumbers = enumeratePrimeNumbers(maxNumber);

		System.out.println(primeNumbers.toString());
	}

	private List<Integer> enumeratePrimeNumbers(int maxNumber) {
		List<Integer> targets = createSearchTargets(maxNumber);

		sieve(targets, maxNumber);

		return targets;
	}

	//Créer une liste de recherche de 2 à maxNumber
	private List<Integer> createSearchTargets(int maxNumber) {
		List<Integer> targets = new ArrayList<>(maxNumber);
		for(int i = MIN_PRIME_NUMBER; i <= maxNumber; i++) {
			targets.add(i);
		}
		return targets;
	}

	//Filtrer les multiples de la première valeur dans la liste de recherche à partir de la liste de recherche
	//Faites ce qui précède jusqu'à ce que la valeur de début de la liste de recherche atteigne la racine carrée de maxNumber.
	private void sieve(List<Integer> targets, int maxNumber) {
		int sqrt = (int)  Math.sqrt(maxNumber);
		for(int i = MIN_PRIME_NUMBER; i <= sqrt; i++) {
			int firstNum = i;
			if(targets.contains(firstNum)) {//★★★ La partie qui détermine s'il s'agit d'un tamis ou non ★★★
				//Puisque le carré de la première valeur a déjà été filtré
				for(int j = firstNum * firstNum; j <= maxNumber; j += firstNum) {
					targets.remove(Integer.valueOf(j));//★★★ Pièce de tamisage ★★★
				}
			}
		}
	}

}

SetImplement.java


package practise.algorithm.eratosthenes.qiita;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class SetImplement {
	private static final int MIN_PRIME_NUMBER = 2;

	public static void main(String[] args) {
		new SetImplement().execute();
	}

	private void execute() {
		Scanner sc = new Scanner(System.in);
		int maxNumber = sc.nextInt();

		Set<Integer> primeNumbers = enumeratePrimeNumbers(maxNumber);

		System.out.println(primeNumbers.toString());
	}

	private Set<Integer> enumeratePrimeNumbers(int maxNumber) {
		Set<Integer> targets = createSearchTargets(maxNumber);

		sieve(targets, maxNumber);

		return targets;
	}

	//Faire une liste numérique de 2 à maxNumber
	private Set<Integer> createSearchTargets(int maxNumber) {
		Set<Integer> targets = new HashSet<>(maxNumber);
		for(int i = MIN_PRIME_NUMBER; i <= maxNumber; i++) {
			targets.add(i);
		}
		return targets;
	}

	//Filtrer les multiples de la première valeur dans la liste de recherche à partir de la liste de recherche
	//Faites ce qui précède jusqu'à ce que la valeur de début de la liste de recherche atteigne la racine carrée de maxNumber.
	private void sieve(Set<Integer> targets, int maxNumber) {
		int sqrt = (int)  Math.sqrt(maxNumber);
		for(int i = MIN_PRIME_NUMBER; i <= sqrt; i++) {
			int firstNum = i;
			if(targets.contains(firstNum)) {//★★★ La partie qui détermine s'il s'agit d'un tamis ou non ★★★
				//Puisque le carré de la première valeur a déjà été filtré
				for(int j = firstNum * firstNum; j <= maxNumber; j += firstNum) {
					targets.remove(j);//★★★ Pièce de tamisage ★★★
				}
			}
		}
	}
}

BooleanArrayListImplement.java


package practise.algorithm.eratosthenes.qiita;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class BooleanArrayListImplement {
	private static final int MIN_PRIME_NUMBER = 2;

	public static void main(String[] args) {
		new BooleanArrayListImplement().execute();
	}

	private void execute() {
		Scanner sc = new Scanner(System.in);
		int maxNumber = sc.nextInt();

		List<Integer> primeNumbers = enumeratePrimeNumbers(maxNumber);

		System.out.println(primeNumbers.toString());
	}

	private List<Integer> enumeratePrimeNumbers(int maxNumber) {
		List<Boolean> targets = createSearchTargets(maxNumber);

		List<Integer> primeNumbers = extracePrimeNumbers(targets);

		return primeNumbers;
	}

	//Créer une liste de recherche booléenne de 0 à maxNumber
	//Commencez à partir de 0 pour définir l'index comme le nombre de cibles de recherche
	//Que ce soit un nombre premier ou non est jugé par booléen
	private List<Boolean> createSearchTargets(int maxNumber) {
		List<Boolean> targets = new ArrayList<>(maxNumber + 1);
		targets.add(false);//Parce que 0 n'est pas un nombre premier
		targets.add(false);//Parce que 1 n'est pas un nombre premier
		for(int i = MIN_PRIME_NUMBER; i <= maxNumber; i++) {
			targets.add(true);
		}
		return targets;
	}

	//Filtrer les multiples de la première valeur de la liste de recherche dans la liste de recherche
	//Faites ce qui précède jusqu'à ce que la valeur de début de la liste de recherche atteigne la racine carrée de maxNumber.
	private List<Integer> extracePrimeNumbers(List<Boolean> targets) {
		int maxNumber = targets.size() - 1;

		sieve(targets, maxNumber);

		List<Integer> primeNumbers = convertToNumList(targets);

		return primeNumbers;
	}

	private void sieve(List<Boolean> targets, int maxNumber) {
		int sqrt = (int)  Math.sqrt(maxNumber);
		for(int i = MIN_PRIME_NUMBER; i <= sqrt; i++) {
			int firstNum = i;
			if(targets.get(i)) {//★★★ La partie qui détermine s'il s'agit d'un tamis ou non ★★★
				//Puisque le carré de la première valeur a déjà été filtré
				for(int j = firstNum * firstNum; j <= maxNumber; j += firstNum) {
					targets.set(j, false);//★★★ Pièce de tamisage ★★★
				}
			}
		}
	}

	private List<Integer> convertToNumList(List<Boolean> targets) {
		List<Integer> numbers = new ArrayList<>();
		for(int i = 0; i < targets.size(); i++) {
			if(targets.get(i)) {
				numbers.add(i);
			}
		}
		return numbers;
	}
}

Résumé de la vitesse

Il s'agit d'un résumé du temps d'exécution (moyenne de 5 exécutions). ʻArrayList est le plus rapide, et ʻArrayList est hors de question. Aucune des implémentations utilisant des tableaux ne se réalisera. .. ..

la mise en oeuvre La limite supérieure est10^5 La limite supérieure est10^6 La limite supérieure est10^7
Implémenté avec ArrayList(ListImplement.java) 3,221 ms Je ne suis pas revenu -
Implémenté avec HashSet(SetImplement.java) 24 ms 118 ms 1,120 ms
ArrayListMis en œuvre en(BooleanArrayListImplement.java) 16 ms 50 ms 1,247 ms
Référence 1 31 ms 276 ms 7,845 ms
Référence 2 4 ms 21 ms 66 ms

Cause de la différence de vitesse

J'ai écrit une note ★ dans le code, mais je pense que les deux points suivants sont les principaux facteurs.

-La partie qui détermine s'il s'agit d'un tamis --Partie de tamisage

Les éléments sont accessibles à chaque endroit, et la méthode d'accès à ce moment est la suivante.

Après tout, l'ordre calculé est ʻArrayListest $ O (n ^ 2 loglogn) $,HashSet et ʻArrayList <Boolean> sont $ O (nloglogn) $ (En regardant les résultats de l'exécution, je ne pense pas que ce soit le cas avec cette implémentation. .) Je pense que c'est. (La partie loglogn a été recherchée sur Google. [Cet article](https://qiita.com/drken/items/872ebc3a2b5caaa4a0d0#%E4%BE%8B-14-%E3%82%A8%E3%83%A9 % E3% 83% 88% E3% 82% B9% E3% 83% 86% E3% 83% 8D% E3% 82% B9% E3% 81% AE% E3% 81% B5% E3% 82% 8B% E3 Il y a aussi% 81% 84-on-loglogn).)

Les tableaux sont plus rapides que ʻArrayList et ʻArrayList <Boolean> que HashSet car il n'y a pas de calcul de valeur de hachage lors de l'accès à l'élément, et il n'y a aucune opération pour étendre le tableau. Probablement parce qu'il n'y a pas d'autres opérations supplémentaires.

Résumé

Quand je l'ai essayé, je me suis senti comme suit.

C'est intéressant de voir beaucoup d'algorithmes que je n'ai jamais vus auparavant quand je fais un pro de la compétition. C'est à cette époque que je souhaite faire bon usage de mon entreprise.

finalement

――Lors de la sélection d'une structure de données de type collection, je l'ai implémentée comme s'il s'agissait d'un ensemble pour éliminer les doublons et d'une liste s'il y avait des doublons. Je suis content de l'avoir remarqué maintenant, simplement parce que cela n'a pas tellement affecté la vitesse que cela s'est avéré être un problème. «Merci à @nkojima pour avoir rédigé un merveilleux article, j'ai pu étudier dur. Je vous remercie. «Je pense qu'il y a beaucoup d'endroits où vous n'avez pas assez étudié, mais s'il y a quelque chose qui ne va pas, j'aimerais que vous jetiez doucement Masakari.

Recommended Posts

Essayez d'implémenter le tamis Eratostenes en utilisant la bibliothèque standard de Java
Essayez le hooking global en Java à l'aide de la bibliothèque JNativeHook
Essayez d'ajouter du texte à une image avec Scala en utilisant la bibliothèque standard de Java
[Java] Essayez de modifier les éléments de la chaîne Json à l'aide de la bibliothèque
Essayez d'utiliser l'API Stream en Java
[Java] Utiliser la technologie cryptographique avec les bibliothèques standard
Essayez d'utiliser la télécommande Wii en Java
Essayez d'accéder à l'ensemble de données depuis Java en utilisant JZOS
Essayez d'utiliser l'analyse syntaxique de l'API COTOHA en Java
Sortie de la valeur maximale d'un tableau à l'aide de la sortie standard Java
Essayez d'utiliser RocksDB avec Java
Essayez de gratter en utilisant Java [Note]
J'ai essayé d'utiliser la bibliothèque CameraX avec Android Java Fragment
Créez un serveur Web simple avec la bibliothèque standard Java com.sun.net.httpserver
Essayez d'implémenter Android Hilt en Java
[Java] Essayez de résoudre le problème de Fizz Buzz en utilisant un traitement récursif
Comparaison Java à l'aide de la méthode compareTo ()
Essayez d'utiliser Redis avec Java (jar)
Bienvenue dans le marais des bibliothèques Java! !!
[Java] Essayez de mettre en œuvre à l'aide de génériques
Essayez d'utiliser le système de messagerie Pulsar
Essayez d'utiliser le traçage de méthode IBM Java
Essayez d'utiliser le SDK Java d'Hyperledger Iroha
[Java] Où avez-vous essayé d'utiliser java
Analyser et objectiver JSON à l'aide de l'annotation @JsonProperty de la bibliothèque Java Jackson
Afficher le calendrier et le jour japonais en utilisant la classe standard java8
Java: essayez d'implémenter vous-même un formateur séparé par des virgules
Essayez d'utiliser le framework Java Nablarch [Application Web]
Essayez d'utiliser || au lieu de l'opérateur ternaire
Formation des nouveaux arrivants à l'aide de la programmation Web-Basic à l'aide de Java-
Étude de Java Essayez d'utiliser un scanner ou une carte
Essayez d'utiliser l'API au format JSON en Java
Essayez d'appeler le service CORBA sur Java 11+
Essayez d'utiliser l'API REST de JobScheduler - implémentation Java RestClient--
[Java] Colorez la sortie standard vers le terminal
Essayez d'utiliser l'API Emotion d'Android
Essayez d'implémenter un serveur GraphQL en utilisant grahpql-java-tools (+ kotlin)
Essayez d'utiliser la classe de test RestClient de JobScheduler REST-API-Java-
ChatWork4j pour l'utilisation de l'API ChatWork en Java
Formation des nouveaux arrivants à l'aide de la programmation / cours Web-Basic en
Essayez d'appeler le service CORBA depuis Spring (Java)
Essayez d'utiliser Sourcetrail (version win) avec du code Java
Essayez d'utiliser l'API Cloud Vision de GCP en Java
Essayez d'utiliser Sourcetrail (version macOS) avec du code Java
Essayez une recherche similaire de recherche d'images à l'aide du SDK Java [Recherche]
Essayez Progate Free Edition [Java II]
Créer une carte multi-touches avec une bibliothèque standard
Afficher "Hello World" dans le navigateur à l'aide de Java
Afficher "Hello World" dans le navigateur à l'aide de Java
[Java] Trouvez le nombre premier avec le tamis Eratostenes
Utilisez une bibliothèque Java externe pour le moment
Essayez la communication en utilisant gRPC sur un serveur Android + Java
Ne reconnaît pas la bibliothèque lors de l'implémentation de jcaptcha
[Java] Essayez de résoudre le problème de Fizz Buzz
Essayez Progate Free Edition [Java I]