Efficient way to calculate the second minimum value

Given the matrix, it is easy to calculate the value and the index of the minimum value:

A = rand(10);
[value, index] = min(A(:));

However, I would also like to restore the second value of min (idem for max).

I can, of course, take either of these two approaches:

  • Convert A to vector and sort it.

    PROS: I can restore the second, third ... n minimum value

    CONS: If A is large, sorting is expensive

  • After the location of point A is located, I can replace this value with a large one (for example, Inf), and then start it again min.

    PROS: cheaper than sorting

    CONS: I have to change my matrix (and save the changed value in aux variable). In addition, restarting min is expensive on a large matrix.

I am wondering if there is a better solution:

min min , ( ). n min, n.

, , .

+6
4

, , , , - . , , , , .

A = rand(10);
[firstMin, firstMinIndex] = min(A(:));
secondMin = min(A(A~=firstMin));
secondMinIndex = find(A==secondMin); % slow, but use only if you need the index

, .

2000x2000 4000x4000 , 3,5 , , .

, mex, n + log n-2, , @luismendotomas.

!

+2

:

a = [53 53 49 49 97 75 4 22 4 37];

first = Inf;
second = Inf;

for i = 1:1:numel(a)
    if (a(i) < first)
        second = first;
        first = a(i);
    elseif (a(i) < second && a(i) ~= first)
        second = a(i);
    end
end

fprintf('First smallest %d\n', first);
fprintf('Second smallest %d\n', second);

a(i) ~= first, 4, 4 4, 23

. SO

0

, (: " " ) - @luismendotomas.

, , k- , , . , 2 0. , , .

k- ., , this

0

beesleep , 2 ( ) , 1 ( ). , find, , .

In fact, to get the index of the second minimum, it is equal to ca. 10 times faster to set the first minimum value inf(as suggested in the question), and then get the index of the second minimum from the function min(as opposed to using find)

[firstMin, firstMinIndex] = min(A(:));
A(firstMinIndex) = inf;
[secondMin, secondMinIndex] = min(A(:));

Here is the code I used to compare this implementation with the one suggested by beesleep :

for i = 1:10

    A = rand(10000);

    tic
    [firstMin, firstMinIndex] = min(A(:));
    secondMin = min(A(A~=firstMin));
    secondMinIndex = find(A==secondMin); % slow, but use only if you need the index
    t1(i) = toc;

    tic
    [firstMin, firstMinIndex] = min(A(:));
    A(firstMinIndex) = inf;
    [secondMin, secondMinIndex] = min(A(:));
    t2(i) = toc;

end

disp(mean(t1) / mean(t2))
0
source

Source: https://habr.com/ru/post/1015311/


All Articles