给定矩阵,可以很容易地计算最小值的值和索引:
A = rand(10);
[value, index] = min(A(:));
但是我还想恢复第二个最小值(同上最大值)。
我当然可以采取以下两种方法中的任何一种:
将A转换为矢量并对其进行排序。
PROS:我可以恢复第二,第三...... n最小值
缺点:如果A很大,排序很昂贵
一旦找到A的最小位置,我可以用一个大的值替换这个值(例如:Inf),然后再次运行min
。
PROS:比排序便宜
缺点:我必须修改我的矩阵(并将修改后的值保存在aux变量中)。在大型矩阵上重新运行min也很昂贵。
我想知道是否有更好的解决方案:
当计算min
时,算法必须跟踪到目前为止找到的最小值,直到新值具有较低的值(然后我们更新该值)。
相反,我们会跟踪到目前为止发现的最后n
分钟值,以便恢复最低n
值。
我可以实现这一点,但我想知道它是否是最佳方法,或者它是否已经实施。
答案 0 :(得分:3)
我不知道在哪种情况下它会比排序更便宜,但是使用以下代码是一种简单但不那么快的方法。我可能错了,但如果您只想要第一分钟和第二分钟,我认为您不能使用内置函数更快。
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随机矩阵进行一些测试之后,似乎这个代码片段比在同一矩阵上应用的sort函数快3.5倍。
如果你真的需要更高的效率,你必须编写自己的mex例程,理论上你可以在n + log n-2比较中获得这两个值,如@luismendotomas提供的链接中所述。< / p>
希望这有帮助!
答案 1 :(得分:0)
一次通过:
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 question
答案 2 :(得分:0)
如前所述,我认为最好的(读取:&#34;最有效的#34;)方法是从@luismendotomas链接实现方法。
但是,如果你想避免自己做太多编程,那么你可以应用一些k近邻算法,因为你的数据有一个下限,例如:如果你的所有数据点都是正数,你可以找到2个最近的邻居为0.虽然我不确定这是否比你最初的建议更快。
对于一个k最近邻算法,请参见例如this
答案 3 :(得分:0)
beesleep已经指出方法2(通过计算最小值两次)比方法1(通过排序)更有效。然而,如上所述,在计算第二个最小值find
的索引的答案中提供的实现非常低效。
事实上,要获得第二个最小值的索引,它是ca. 快10倍将第一个最小值设置为inf
(如问题中所示),然后从min
函数获取第二个最小值的索引(与使用相反) find
)
[firstMin, firstMinIndex] = min(A(:));
A(firstMinIndex) = inf;
[secondMin, secondMinIndex] = min(A(:));
以下是我用来将此实现与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))