Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.05;
Скачать: CL | DM;

Вниз

Самое эффективное решение   Найти похожие ветки 

 
Rwer   (2006-10-16 16:28) [0]

Как решить такую простую задачку самым эффективным способом:
Дан массив чисел, выбрать 3 наибольших.
1 самый тупой способ: осортировать массив вывести 3 последних элемента.
2 способ: три раза проходить по массиву и вычислять минимальное значение.

А как можно это реализовать самым лучшим способом?


 
Alien1769 ©   (2006-10-16 16:33) [1]

функция екселя тебе поможет :))


 
Johnmen ©   (2006-10-16 16:35) [2]


>  выбрать 3 наибольших.


> вычислять минимальное значение.

>

Те.е минимальное значение называется "наибольшее"? :)))

3 один раз пройти по массиву, определяя святую троицу чисел...


 
Sandman29 ©   (2006-10-16 16:35) [3]

3) решить задачу в лоб. то есть пройтись один раз и запоминать 3 наибольших.


 
Alien1769 ©   (2006-10-16 16:38) [4]


> и запоминать 3 наибольших.

чисел без знака.


 
palva ©   (2006-10-16 16:39) [5]

Начать с того, что запомнить три первых элемента массива вместе с их индексами в качестве кандидатов. Далее просматривать оставшиеся элементы массива, и если очередной элемент больше какого-нибудь кандидата, то заменить этот кандидат текущим элементом.


 
Jeer ©   (2006-10-16 16:41) [6]

зависит от выбранного способа сортировки и размера массива.
т.е. для первого и второго случаев существует некоторая "цена" операции.
Если отобразить на графике зависимость от N для этих двух случаев, то при нелинейном характере одной из операций возможно пересечение графиков в точке, где "цена" одинакова.

Для второго случая ориентировочно "цена" == 3*K*N, т.е. линейная зависимость.


 
TUser ©   (2006-10-16 17:44) [7]

Сотворить стек из трех элементов и пихать туда. Пример
procedure Up (var S: TStack; N: integer);
begin
 with S do begin
   if N < length (Vects) - 1 then
   with Vects[N] do
     SetInStack (S, N+1, FileName, Atom, VLen);
   end;
end;

procedure Push (var Stack: TStack; Name, Atm: string; Len: cardinal);
var i: integer;
   f: boolean;
begin
 with Stack do begin
   i := Count-1;
   if Count < MaxCount then
     GrowStack (Stack);
   f := true;
   while f and (i >= 0) do
     if Vects[i].VLen > Len then begin
       Up (Stack, i);
       dec (i);
       end else f := false;
   if (not f) or (i < 0) then
   if i < MaxCount - 1 then
     SetInStack (Stack, i+1, Name, Atm, Len);
   end;
end;

procedure PushStruct (S: TStructure);
var i: integer;
begin
 with S do
   for i := 0 to MolCount-1 do
     with Molecules[i] do
     Push (MyStack, FileName, Line, Sums[NVector-1]);
end;


 
Ketmar ©   (2006-10-16 18:06) [8]

сделать SQL-таблицу, всё занести, потом выбрать %-)


 
oldman ©   (2006-10-16 18:57) [9]

а почему способ 1 "самый тупой", если задача сводится к поиску 3 максимумов???
или это я "самый тупой"?


 
TUser ©   (2006-10-16 19:01) [10]

> oldman ©   (16.10.06 18:57) [9]

Ясно, что [7] быстрее.


 
oldman ©   (2006-10-16 19:04) [11]


> TUser ©   (16.10.06 19:01) [10]


Писать дольше.
И думать больше.


 
default ©   (2006-10-16 19:33) [12]

2 способ вполне и вполне
по крайней мере для немалых массивов я пути лучше не вижу


 
default ©   (2006-10-16 20:23) [13]

возможный способ реализации 2 способа

public static int[] GetThreeMaxInt(int[] arr)
       {
           if (arr == null) throw new ArgumentNullException();
           if (arr.Length < 3) throw new ArgumentOutOfRangeException("argument must be >= 3");
           int max;
           int[] res = new int[3];
           int[] ind = new int[3];
           for (int i = 0; i < 3; i++)
           {
               ind[2-i] = i;
               max = arr[i];
               for (int j = i+1; j < arr.Length; j++) {
                   if (arr[j] > max)
                   {
                       ind[2-i] = j;
                       max = arr[j];
                   }
               }
               res[2-i] = max;
               arr[ind[2-i]] = Int32.MinValue;
           }
           for (int i = 0; i < 3; i++) arr[ind[i]] = res[i];
           return res;
       }
       
       static void Main(string[] args)
       {
           foreach (int el in GetThreeMaxInt(new int[] {4, 8, 10, 2, 1, 16, 19}))
               Console.WriteLine(el);
       }


 
Rwer   (2006-10-16 22:12) [14]


> procedure Up (var S: TStack; N: integer);begin  with S do
> begin    if N < length (Vects) - 1 then    with Vects[N]
> do      SetInStack (S, N+1, FileName, Atom, VLen);    end;
> end;procedure Push (var Stack: TStack; Name, Atm: string;
>  Len: cardinal);var i: integer;    f: boolean;begin  with
> Stack do begin    i := Count-1;    if Count < MaxCount then
>      GrowStack (Stack);    f := true;    while f and (i
> >= 0) do      if Vects[i].VLen > Len then begin        Up
> (Stack, i);        dec (i);        end else f := false;
>    if (not f) or (i < 0) then    if i < MaxCount - 1 then
>      SetInStack (Stack, i+1, Name, Atm, Len);    end;end;
> procedure PushStruct (S: TStructure);var i: integer;begin
>  with S do    for i := 0 to MolCount-1 do      with Molecules[i]
> do      Push (MyStack, FileName, Line, Sums[NVector-1]);
> end;


А покороче нельзя 3 числа найти никак??
Я вот подумал... что лучший способ это пройти один раз по массиву и выбрать эти три числа. А как реализовать?
может, например так:

max1:=-MaxInt;  max2:=max1; max3:=max;
for i:=1 to n do begin
 if a[i]>max1 then max1:=a[i];
 if (a[i]>max2) and (a[i]<max1) then max2:=a[i];
 if (a[i]>max3) and (a[i]<max2) then max3:=a[i];
end;

Ну что скажете? Предложите свои варианты!


 
Rwer   (2006-10-16 22:15) [15]

Вот мудрость:
Настоящий программист никогда не делает всё хорошо с первого раза, он понимает важность патчей


 
homm ©   (2006-10-16 22:35) [16]


>
> max1:=-MaxInt;  max2:=max1; max3:=max;
> for i:=1 to n do begin
>  if a[i]>max1 then max1:=a[i];
>  if (a[i]>max2) and (a[i]<max1) then max2:=a[i];
>  if (a[i]>max3) and (a[i]<max2) then max3:=a[i];
> end;


на вскидку: из последовательности
182838 вернет 832


 
default ©   (2006-10-16 22:45) [17]

я же дал код

       public static int[] GetThreeMaxInt(int[] arr)
       {
           if (arr == null) throw new ArgumentNullException();
           if (arr.Length < 3) throw new ArgumentOutOfRangeException("argument must be >= 3");
           int[] max = new int[3];
           int[] ind = new int[3];
           for (int i = 0; i < 3; i++)
           {
               max[2-i] = arr[0];
               ind[2-i] = 0;
               for (int j = 1; j < arr.Length; j++) {
                   if (arr[j] > max[2-i])
                   {
                       ind[2-i] = j;
                       max[2-i] = arr[j];
                   }
               }
               arr[ind[2-i]] = Int32.MinValue;
           }
           for (int i = 0; i < 3; i++) arr[ind[i]] = max[i];
           return max;
       }

p.s. в предыдущем была ошибка писал на скорую руку


 
homm ©   (2006-10-16 22:49) [18]


> Rwer   (16.10.06 16:28)


> Как решить такую простую задачку самым эффективным способом:



> [17] default ©   (16.10.06 22:45)


> for (int i = 0; i < 3; i++)
>            {
>                max[2-i] = arr[0];
>                ind[2-i] = 0;
>                for (int j = 1; j < arr.Length; j++) {
>                    if (arr[j] > max[2-i])
>                    {
>                        ind[2-i] = j;
>                        max[2-i] = arr[j];
>                    }
>                }
>                arr[ind[2-i]] = Int32.MinValue;
>            }


что-то мне не кажется что одно с другим карелирует.


 
default ©   (2006-10-16 23:10) [19]

homm ©   (16.10.06 22:49) [18]
найди способ эффективнее
если делять за один проход, то быстрее не будет только мороки больше


 
Sandman29 ©   (2006-10-17 09:15) [20]

default ©   (16.10.06 23:10) [19]

Если значение меньше третьего, то получится всего одно сравнение. То есть для трехпроходного метода K=3, а для третьего метода K чуть больше 1.


 
evvcom ©   (2006-10-17 10:51) [21]

var a,b,c,i: Integer;
begin
 a := -MaxInt;
 b := -MaxInt;
 c := -MaxInt;
 for i := 0 to High(Arr) do
   if Arr[i] > с then
     if Arr[i] > b then begin
       c := b;
       if Arr[i] > a then begin
         b := a;
         a := Arr[i];
       end
       else
         b := Arr[i];
     end
     else
       c := Arr[i];
end;

Ну плюс проверки разные, если охота. :)


 
default ©   (2006-10-17 13:00) [22]

Sandman29 ©   (17.10.06 09:15) [20]
да, таки побыстрее будет
я почему-то на сравнения только ориентировался(присваивания не брал)
а по сравнениям способ 2 чуть получше чем [21] в его худшем случае
поэтому я и подумал что игра не стоит свеч:)


 
TUser ©   (2006-10-17 13:03) [23]

> 2 способ вполне и вполне по крайней мере для немалых массивов я пути лучше не вижу

Опять же см. [7]. Там требуется один проход по массиву + n проходов по вспомогательному массиму длины 3.

Ну, впрочем, не нравится, - ходите три раза.


 
Jeer ©   (2006-10-17 13:54) [24]

default ©   (17.10.06 13:00) [22]

Способ [21] пасует только перед отсортированным в "нехорошем" порядке массивом.


 
default ©   (2006-10-17 13:59) [25]

Jeer ©   (17.10.06 13:54) [24]
да, для него такой массив не подарок
но он и при таком не пасует за счёт меньшего числа присваиваний


 
Jeer ©   (2006-10-17 14:04) [26]

Пасует перед стеком в простейшей его форме:

procedure Search_02;
var i: integer;
begin
for i := 0 to High(Arr) do begin
 if (Arr[i] > a) then begin
    c := b;
    b := a;
    a := Arr[i];
  end
 else
  if (Arr[i] > b) then begin
      c := b;
      b := Arr[i];
    end
  else
    if Arr[i] > c then c := Arr[i];
end;
end;



Страницы: 1 вся ветка

Текущий архив: 2006.11.05;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.043 c
15-1161236054
Rentgen
2006-10-19 09:34
2006.11.05
Ord и Chr на Builder C++


15-1160828553
PHPDeveloper
2006-10-14 16:22
2006.11.05
Assembler


15-1161225001
Slider007
2006-10-19 06:30
2006.11.05
С днем рождения ! 19 октября


2-1161188335
fog
2006-10-18 20:18
2006.11.05
Печать графики


2-1161582359
X_ksandr_X
2006-10-23 09:45
2006.11.05
сортирвка DbGrid