Java 7 이상, TIO에서 30 초 안에 n = 50
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Random;
class Main{
public static void main(String[] a){
int n=50;
Random randomGenerator = new Random();
int i = n+1;
int squaredN = n*n;
int[]randomIntegers = new int[i];
randomIntegers[n] = squaredN;
while(true){
for(i=n; i-->1; ){
randomIntegers[i] = randomGenerator.nextInt(squaredN);
}
Set<Integer> result = new HashSet<>();
Arrays.sort(randomIntegers);
for(i=n; i-->0; ){
result.add(randomIntegers[i+1] - randomIntegers[i]);
}
if(!result.contains(0) && result.size()==n){
System.out.println(result);
return;
}
}
}
}
이 도전 과제의 코드 골프 버전에 대한 내 대답 의 ungolfed 버전은 하나의 사소한 변경 만 있습니다. 범위의 정수 java.util.Random#nextInt(limit)
대신 약 2 배 빠릅니다 .(int)(Math.random()*limit)
[0, n)
온라인으로 사용해보십시오.
설명:
사용 된 접근법 :
코드는 두 부분으로 나뉩니다.
- 에
n
합산되는 임의의 정수 목록을 생성합니다 n squared
.
- 그런 다음 모든 값이 고유하고 0이 아닌지 확인하고 둘 중 하나라도 거짓이면 1 단계를 다시 시도하여 결과가 나올 때까지 헹구고 반복합니다.
1 단계는 다음 하위 단계로 수행됩니다.
1) n-1
범위 내에서 임의의 정수로 구성된 배열을 생성하십시오 [0, n squared)
. 그리고 추가 0
하고 n squared
이 목록. 이것은 O(n+1)
성능 에서 이루어집니다 .
2) 그런 다음 내장으로 배열을 정렬합니다 java.util.Arrays.sort(int[])
. 이것은 O(n*log(n))
문서에 명시된 것처럼 성능 이 수행됩니다 .
지정된 정수 배열을 오름차순으로 정렬합니다. 정렬 알고리즘은 Jon L. Bentley와 M. Douglas McIlroy의 "정렬 기능 엔지니어링", Software-Practice and Experience, Vol. 23 (11) P. 1249-1265 (1993 년 11 월). 이 알고리즘은 다른 빠른 정렬이 2 차 성능으로 저하되도록하는 많은 데이터 세트에서 n * log (n) 성능을 제공합니다.
3) 각 쌍의 차이를 계산하십시오. 이 결과 차이 목록에는 n
에 합산 된 정수 가 포함 됩니다 n squared
. 이것은 O(n)
성능 에서 이루어집니다 .
예를 들면 다음과 같습니다.
// n = 4, nSquared = 16
// n-1 amount of random integers in the range [0, nSquared):
[11, 2, 5]
// Add 0 and nSquared to it, and sort:
[0, 2, 5, 11, 16]
// Calculate differences:
[2, 3, 6, 5]
// The sum of these differences will always be equal to nSquared
sum([2, 3, 6, 5]) = 16
따라서 위의 세 단계는 기본 무차별 대입 인 2 단계 및 전체 주변의 루프와 달리 성능에 매우 좋습니다. 2 단계는 다음 하위 단계로 나뉩니다.
1) 차이점 목록이 이미에 저장되어 있습니다 java.util.Set
. 이 세트의 크기가 같은지 확인합니다 n
. 그렇다면, 우리가 생성 한 모든 임의의 값이 고유하다는 것을 의미합니다.
2) 그리고 그것은 또한이 더 포함되어 있는지 확인하지 않습니다 0
도전의 범위에서 임의의 값을 요구하기 때문에, 설정의 [1, X]
경우, X
인 n squared
마이너스의 합 [1, ..., n-1]
에 의해 명시된 바와 같이, @Skidsdev 아래의 코멘트에.
위의 두 옵션 중 하나 (모든 값이 고유하지 않거나 0이 존재하지 않음) 인 경우 새 배열을 생성하고 1 단계로 재설정하여 다시 설정합니다. 결과가 나올 때까지 계속됩니다. 이로 인해 시간이 약간 다를 수 있습니다. 나는 TIO에서 3 초에 한 번 완료 n=50
되지만 55 초에 한 번 완료되는 것을 보았습니다 n=50
.
균일 성 입증 :
나는 이것을 완전히 정직하게 증명하는 방법을 완전히 확신하지 못한다. 는 java.util.Random#nextInt
해당 문서에 설명 된대로, 확실히 균일 :
int
이 난수 생성기 시퀀스에서 균일하게 분포 된 다음 의사 난수 값을 반환합니다 . 일반적인 계약은 nextInt
하나의 int
값이 의사 난수로 생성되어 반환 된다는 것 입니다. 가능한 모든 32 개의int
값은 (대략) 동일한 확률로 생성됩니다.
이러한 (정렬 된) 임의의 값 자체의 차이는 물론 균일하지 않지만 전체적으로 세트는 균일합니다. 다시 말하지만, 이것을 수학적으로 증명하는 방법을 잘 모르겠지만 여기에 10,000
생성 된 세트를 for n=10
와 함께 맵에 넣는 스크립트가 있습니다 ( 대부분의 세트는 고유합니다). 일부는 두 번 반복되었습니다. 최대 반복 발생 범위는 일반적으로 범위 [4,8]
입니다.
설치 지침 :
Java는 Java 코드를 작성하고 실행하는 방법에 대한 많은 정보를 제공하는 잘 알려진 언어이므로 간단히 설명하겠습니다.
내 코드에 사용 된 모든 도구는 Java 7에서 사용할 수 있습니다 (아마도 Java 5 또는 6에서도 가능하지만 경우에 따라 7을 사용하십시오). Java 7이 이미 보관되어 있다고 확신하므로 Java 8을 다운로드하여 코드를 실행하는 것이 좋습니다.
개선에 관한 생각 :
0 확인을 개선하고 모든 값이 고유한지 확인하고 싶습니다. 0
배열에 추가하는 임의의 값이 아직 포함되어 있지 않은지 확인하여 이전에 확인할 수 있었지만 몇 가지 의미가 있습니다. 배열은 ArrayList
내장 메소드를 사용할 수 있도록 해야합니다 .contains
. 목록에없는 임의의 값을 찾을 때까지 while 루프를 추가해야합니다. 제로를 확인하는 것은 지금으로 수행되기 때문에 .contains(0)
(한 번만 체크) 설정에, 그것은 성능과 루프를 추가 비교하여, 그 시점에서 그것을 확인하는 가장 가능성이 더 나은 .contains
적어도 확인됩니다 목록에 n
배 하지만 대부분 더 많을 것입니다.
고유성 검사 의 경우 프로그램의 1 단계 이후에 n
합산되는 임의의 정수만 n squared
있으므로 모든 것이 고유한지 여부를 확인할 수 있습니다. 배열 대신 정렬 가능한 목록을 유지하고 그 사이의 차이점을 확인할 수는 있지만, Set
세트에 넣는 것보다 성능을 향상시키고 세트의 크기가 n
한 번 인지 확인 하는 것이 심각하다고 의심합니다 .