znajdź element w środku stosu

Zadano mi to pytanie w wywiadzie.Problem polegał na tym, że otrzymałbym stos i musiałem znaleźć element w środkowej pozycji stosu.indeks " top " nie jest dostępny (więc nie pop () top / 2 razy i nie zwraca odpowiedzi).Załóżmy, że osiągniesz dno stosu, gdy pop() zwróci -1.Nie używaj żadnej dodatkowej struktury danych.

Eg:

stack   index
----- 
 2    nth element
 3
 99
 .
 1    n/2 th element
 .
 -1   bottom of the stack(0th index)

Odpowiedź: 1 (nie miałem na myśli mediany.Znajdź element w pozycji środkowej)

Czy rekurencja jest jedyną sposób?

Dzięki,

Psy

Author: psy, 2011-09-18

6 answers

Przejdź przez stos, Oblicz głębokość i w drodze powrotnej zwróć odpowiedni element.

int middle(stack* s, int n, int* depth) {
  if (stack_empty(s)) {
    *depth = n;
    return 0; //return something, doesn't matter..
  }
  int val = stack_pop(s);
  int res = middle(s, n+1, depth);
  stack_push(s, val);
  if (n == *depth/2)
    return val;
  return res;
}

int depth;
middle(&stack, 0, &depth);

Uwaga: tak, rekurencja jest jedynym sposobem. Nie znając głębokości stosu oznacza, że musisz gdzieś przechowywać te wartości.

 13
Author: Karoly Horvath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-18 12:40:15

Rekurencja nigdy nie jest jedynym sposobem;)

Jednakże, rekurencja zapewnia dodatkowy stos (tj. parametry funkcji i zmienne lokalne) i wydaje się, że potrzebujesz dodatkowej pamięci do przechowywania przejeżdżanych elementów, w takim przypadku wygląda na to, że rekurencja może być jedynym sposobem, biorąc pod uwagę to ograniczenie.

 6
Author: Ofir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-18 12:16:27

Oto jedno rozwiązanie: weź dwa wskazówki, jeden z nich posuwaj się dwa kroki na raz (szybko), drugi tylko jeden krok na raz (wolno). Jeśli szybki osiągnie dno, zwróć powolny wskaźnik, który wskazuje na środkowy indeks. Nie wymaga rekurencji.

int * slow = stack;
int * fast = stack;
while(1) {
    if(STACK_BOTTOM(fast)) return slow;
    fast--;
    if(STACK_BOTTOM(fast)) return slow;
    slow--;
    fast--;
}
 0
Author: rumpel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-18 12:04:00

Rekurencja wydaje się być jedynym sposobem. Jeśli spróbujesz użyć koncepcji szybkiego i wolnego wskaźnika podczas wyświetlania, będziesz musiał gdzieś przechowywać wartości, co narusza wymóg braku dodatkowej struktury danych.

 0
Author: Anoop Menon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-18 15:37:20

To pytanie jest oznaczone c, więc dla języka programowania c zgadzam się, że rekurencja jest jedynym sposobem. Jeśli jednak obsługiwane są funkcje anonimowe pierwszej klasy, można je rozwiązać bez rekursji. Niektóre pseudo kod (używając składni lambda Haskella):

n = 0
f = \x -> 0        # constant function that always returns 0

while (not stack_empty) do
    x = pop
    n = n+1
    f = \a -> if (a == n) then x else f(a)

middle = f(n/2)    # middle of stack

# stack is empty, rebuilt it up to middle if required 
for x in (n .. n/2) do push(f(x))

UWAGA: podczas pętli while nie ma (rekurencyjnego) wywołania f. f(a) w gałęzi else służy tylko do konstruowania nowego (!) funkcji, która jest wywoływana ponownie f.

Zakłada się, że stos ma 3 elementy 10, 20, 30 (od dołu do góry) to w zasadzie konstruuje lambda

(\a -> if a==1
       then 30
       else (\b -> if b==2
                   then 20
                   else (\c -> if c==3
                                  then 10
                                  else (\d -> 0)(c)
                        )
                        (b)
            )
            (a)
)

Lub nieco bardziej czytelny

f(x) = if x==1 then 30 else (if x==2 then 20 else (if x==3 then 10 else 0)) 
 0
Author: nimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-20 16:47:11

"... Nie używaj żadnej dodatkowej struktury danych. ..."

Wtedy zadanie jest nierozwiązywalne, ponieważ potrzebujesz miejsca, w którym można przechowywać wyskakujące dane. Do rekurencji potrzebny jest inny stos, który jest również strukturą danych. Nie ma sensu zabraniać jakiejkolwiek struktury danych i zezwalać na rekurencję.

 0
Author: TMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-22 11:41:46