2012-05-12 2 views
1

범위가 설정되어 있고 반복 값이 없는지 확인하면서 해당 범위 (10 %)에서 임의의 숫자 집합을 선택하고 싶습니다.반복되는 값 피하기

내 프로그램에서 어떻게 코드를 작성합니까?

아래는 추출물입니다.

// Number of Items  
int range = numberOfItems [itemNumber - 1]; 
// Determine 10 percent of the given range 
int tenPercentOfRange = (int)(range * 0.1); 
int number = 0; 
int[] numbers = new int[tenPercentOfRange]; 

int index = 0; 

for(;index < tenPercentOfRange;) 
{ 
    // Randomly select 10% of the items for a given item. 
    number = (int) (range * Math.random()) + 1; 
    if(!Arrays.asList(numbers).contains(number)) 
    { 
    numbers[index] = number; 
    index++; 
    // .................. 
+1

사용 HashSet에, 그것은 그렇지 않으면 재생 사용할 수 있습니까? – DarthVader

+1

관련없는 팁 : 지금 int 배열을 사용하는 대신 ArrayList 을 사용할 수 있습니다. – AHungerArtist

+0

@DarthVader는 해시 설정을하지 않습니다 (일반적인 해시와 동일). 자동으로 반복되는 항목이 삭제됩니다. –

답변

2

가장 쉬운 방법 (안 가장 효율적인는하지만) 아마 모든 요소 목록을 채우는 Collections.shuffle()을 사용하고, 처음 10 %의 요소를 선택하는 것입니다.

순열에 동일한 엔트리가 두 번 나타나지 않으므로 (이 방법으로 입력했다고 가정하면) 처음 10 % 요소도 고유하므로 적합합니다.

0

정수 범위의 10 % 만 필요한 경우 고유 번호를 얻을 때까지 반복하는 방식이 더 효율적입니다. 중복을 효율적으로 검사하기 위해 LinkedHashSet을 사용합니다.

final int range = 1000, sampleSize = range/10; 
final Set<Integer> rnds = new LinkedHashSet<Integer>(); 
final Random r = new Random(); 
for (int i = 0; i < sampleSize;) if (rnds.add(r.nextInt(range) + 1)) i++; 
System.out.println(rnds); 
final int[] result = new int[sampleSize]; 
int i = 0; 
for (int nr : rnds) result[i++] = nr; 
2

사용 collection.shuffle() 및 지정된 크기의 하위 목록을 선택하거나 목록에서 값을 넣어 X 시간에 대한 지수

found.add (list.remove (random.nextInt (list.size())); 

에서 요소를 제거합니다. 각 단계에서 목록의 크기가 줄어들며 요소가 두 번 나타나지 않습니다.

그러나 매우 큰 범위의 경우 - 유효한 길이의 범위를 말하고, 셔플 또는 값을 선택하는 목록을 작성하는 것은 적절하지 않습니다.

그래서 Set을 만들고 임의의 Values를 선택하고 set.size()가 필요한 크기와 같을 때까지 목록에 추가하십시오.

의 Runnable 예 : 숫자가 설정에없는 경우

import java.util.*; 

public class Empty { 

    static Random random = new Random(); 

    public static void main (String args []) 
    { 
     show (pick (10, 100)); 
     show (securePick (10, 100000)); 
    } 

    static public List <Integer> pick (int n, int max) { 
     List <Integer> result = new ArrayList <Integer>(); 
     List <Integer> range = new ArrayList <Integer> (max); 
     for (int i= 0; i < max; ++i) 
      range.add (i); 
     for (int i= 0; i < n; ++i) 
      result.add (range.remove (random.nextInt (range.size()))); 
     return result; 
    } 

    static public Set <Integer> securePick (int n, int max) { 
     Set <Integer> result = new HashSet <Integer>(); 
     while (result.size() < n) 
      result.add (random.nextInt (max)); 
     return result; // <Integer> 
    } 

    public static void show (List <Integer> liste) 
    { 
     System.out.print ("["); 
     for (int i : liste) 
      System.out.print (i + ", "); 
     System.out.println ("\b\b]"); 
    } 

    public static void show (Set <Integer> liste) 
    { 
     System.out.print ("["); 
     for (int i : liste) 
      System.out.print (i + ", "); 
     System.out.println ("\b\b]"); 
    } 
} 
+0

보안 픽업을 좋아합니다 – miks

+0

예. securePick의 유일한 문제는 1M 값 중 999'999를 선택하려고 시도하지만 역도를 선택하지 말고 자신이 유죄 인 경우입니다.) –

+1

예하지만이 경우 메소드가 매우 짧게 향상 될 수 있습니다. n> max/2이면 inverse anka와 함께 가고, 역행렬을 사용하십시오. – miks

관련 문제