2012-03-23 10 views

Odpowiedz

5

coś takiego:

int count = 0; 
int index = -1; 
for (int i = 0; i != n; ++i) 
{ 
    if (values[i]) 
    { 
     ++count; 
     if (unit_random <= 1.0f/count) 
     { 
      index = i; 
     } 
    } 
} 

Więc dla 4 wartości na przykład uzyskać następujące prawdopodobieństwa dla swoich indeksach:

1: (1/1) * (1/2) * (2/3) * (3/4) = 1/4 
2: (1/2) * (2/3) * (3/4) = 1/4 
3: (1/3) * (3/4) = 1/4 
4: 1/4 = 1/4 

EDIT: Jak Steve Jessop wskazał na zmiennoprzecinkowych porównania ostatecznie doprowadzi do bardzo niejednolitej selekcji. Zakładając unit_random jest zdefiniowany jako rand()/RAND_MAX porównania mogą być zmienione na:

typedef unsigned long long u64; 
u64 product = u64(count) * rand(); 
if (product <= u64(RAND_MAX)) 

To nie dadzą doskonały rozkład ze względu na dyskretny charakter rand ale będzie lepiej.

+0

Niestety, to zapomniał słowa. Chciałem powiedzieć: zwróć indeks losowej wartości PRAWDZIWEJ ... Nie tylko pierwszej, którą znajdziemy. Ale funkcja powinna losowo zwracać dowolny z indeksów zawierających PRAWDA. – PaulV

+0

@PaulV Dokładnie to robi ta funkcja. –

+0

@Nick Tak, ale zredagowałem swoją odpowiedź;) –

0

Nie jest do końca jasne, co oznacza "losowo distibuted". Czy to oznacza "z nieznaną dystrybucją"? Jeśli tak, to udawajmy, że wszystkie możliwe rozkłady są równie prawdopodobne, więc "oczekiwana dystrybucja" (jak w "wartości oczekiwanej") jest jednolita ("średnia" wszystkich możliwych rozkładów). Następnie dowolny indeks ma wartość PRAWDA z prawdopodobieństwem 1/2. Zatem twoim zadaniem staje się jak najszybsze iterowanie przez tablicę. Zacznij od początku, tak jakbyś normalnie iterował tablicę, dopóki nie napotkasz wartości PRAWDA.

+0

Mam na myśli, że nie ma wzorca dla wartości. Nie śledzą żadnej funkcji dystrybucji. – PaulV

+1

Zgadnij, że oznacza [rozkład jednostajny] (http://en.wikipedia.org/wiki/Uniform_distribution_ (dyskretny)), prawda? ;) –

+0

@PaulV: "losowo rozpowszechniany" jest prawdopodobnie złym zwrotem do użycia, jeśli masz na myśli "nie śledzą żadnej funkcji dystrybucji". Mogłeś powiedzieć "arbitralne wartości boolowskie" lub po prostu "wartości logiczne". Wtedy musiałbyś zdefiniować, co masz na myśli, mówiąc "najszybszy", ponieważ jeśli nie masz dystrybucji dla wartości, to nie ma czegoś takiego jak "oczekiwany czas pracy" dla dowolnego algorytmu, którego prędkość zależy od wartości. –

0

Aby go zwrócić, musisz najpierw policzyć wartości True (nie ma sposobu, aby je pominąć) i zebrać ich indeksy w innej tablicy. A po zliczeniu trzeba po prostu wygenerować losową liczbę całkowitą od 0 do N-1 (gdzie N jest liczbą wartości True) i wybrać wartość z utworzonej tablicy.

w pseudo-python:

indices=[] 

for i,val in enumerate(arr): 
    if val: 
     indices.append(i) 
randi = randint(0,len(indices)-1) 
return indices[randi] 
1

Najszybszym rozwiązaniem - zakładając, że nie wielokrotnie wybrać na tej samej tablicy - jest, aby wybrać indeks losową, zwrócić go, czy to prawda, i powtórzyć, jeśli nie. W najlepszym przypadku, gdy wszystkie wpisy są prawdziwe, jest to O (1); w najgorszym przypadku, gdy tylko jeden wpis jest prawdziwy, jest to O (n) (każda próba ma 1/n szansę na trafienie w jedyną prawdziwą wartość, co oznacza spodziewaną liczbę prób n). To nie jest gorsze niż jakiekolwiek inne opublikowane rozwiązania.

Jeśli spodziewasz się, że tablica będzie prawie zawsze fałszywa, możesz wybrać inne rozwiązanie, ponieważ wariancja w czasie wykonywania tej przypadkowej metody będzie wysoka.

+1

"To nie jest gorsze niż jakiekolwiek inne opublikowane rozwiązanie" - złożoność nie jest, ale wykorzystuje pamięć podręczną mniej wydajnie niż odpowiedź Andreasa. A FWIW, kod Andreasa przykrywa awarię, a takie podejście nie. Być może "najlepszą" rzeczą (odejście od oczekiwanego vs. najgorszego przypadku) jest wykonanie niewielkiej liczby losowych próbek, a jeśli żadna z nich nie znajdzie prawdziwej wartości, to wyciągnij wniosek, że tablica jest rzadka i cofnij się do rozwiązania Andreasa lub podobnego . –

0

Proste rozwiązanie: Generowanie możliwych permutacji indeksów (1: n) i rzędu permutacji tego wskaźnika powrotnej, gdy odpowiednia wartość prawda

def randomTrue(x): 
    perm = randomPermute(0:len(x)) 
    for i in perm: 
     if x[i]: 
      return i 
Powiązane problemy