【问题标题】:How can I find the indices of the 2 smallest elements in a vector without sorting?如何在不排序的情况下找到向量中两个最小元素的索引?
【发布时间】:2014-09-17 04:05:09
【问题描述】:

我试图找到一个 1xn 向量的两个最小元素。问题是我无法对其进行排序,因为索引线性依赖于值(因此对值进行排序会导致原始索引)并且 0 可以是元素之一。此外,元素可以重复。这是我的代码的简化示例:

a = [1,5,8,7,1];

find(a==min(a))

ans =

 1     5

对于a,这是我所期待的答案。

b = [0,8,6,1,9];

find(b==min(b))

ans =

 1

对于 b,我需要它来找到 0 和 1,因此它应该分别返回 1 和 4 作为索引。提前致谢!

【问题讨论】:

  • 关于搞砸原始索引:假设在你的向量a 旁边有一个时间向量t = [1,2,3,4,5]。如果你这样做,你可以用同样的方式排序:[~, idx] = sort(a)。现在执行[t(idx)', a(idx)'] 会给你一个表格,其中包含新排序的ta
  • 您期望[0 1 1 2 3 4] 的输出是什么?

标签: matlab sorting vector


【解决方案1】:

Phil Goddard 的回答完全可以接受。但是,您确实说过要在不排序的情况下执行此操作,所以我假设您根本不想使用 sort 函数。你可以做的是使用min 两次。一旦您第一次调用它并找到最小元素的索引,您将在数组中将此位置设置为NaN,然后再运行min。通过将位置设置为NaN,您将有效地跳过等于该时间点最小值的元素。第二次调用min 后,您将获得第二小的元素。

之后您需要做的一件小事是在第一次调用min 之后清除您在数组中设置的NaN。您可以通过提取第一次调用后的最小值以及该最小值所在的位置来执行此操作。一旦您第二次调用min,您就会将第一个最小值从NaN 重置回其原始值的位置。

换句话说:

a = [1,5,8,7,1];
[min1,ind1] = min(a);
a(ind1) = NaN;
[~,ind2] = min(a);
a(ind1) = min1; %// Copy back to ensure we get original data back

ind1ind2 将包含a 中两个最小值的位置。以你的例子,我得到:

disp([ind1 ind2])

1     5

同样,对于b,这就是我们通过上面的代码得到的:

disp([ind1 ind2])

1     4

【讨论】:

  • 我没有进行基准测试,但我认为这比 Phil 的答案要快,至少对于(非常)大矩阵而言。 Matlab 的 sort 是 big-o (n log(n)) 的快速排序,而 find 显然是 (n)。
  • @RobertP。 - 凉爽的!在您提出之前,我实际上并没有考虑过效率。这实际上将执行两次线性搜索,而 Phil 的方法将首先对元素进行排序,然后吐出最小的两个元素的位置。我一直喜欢速度!
  • 我同意菲尔的回答很好,但它不适用于我的问题..或者更确切地说,它没有解决它。这种方法效果很好,不会搞乱数组的顺序。谢谢!
  • @PaulKiripaul - 酷!别客气!顺便说一句,我做了一个小改动,这样你仍然可以做同样的事情,但不需要复制数组。我想如果你要为一个大型数组执行此操作,那么在周围拥有该数组的另一个副本可能不是好兆头。看看吧,祝你好运!
【解决方案2】:

您应该使用排序的第二个输出,

>> [~,idx] = sort(a);
>> idx(1:2)
ans = 
  1  5
>> [~,idx] = sort(b);
>> idx(1:2)
ans = 
  1  4

【讨论】:

  • 您好菲尔,谢谢您的回复。我按照您建议的方式尝试了它,不幸的是它没有做我需要它做的事情。例如:
  • 抱歉,没能及时完成我的评论。简而言之,我感谢您的回答,但它不适用于我的具体问题。
猜你喜欢
  • 2012-12-17
  • 2015-10-07
  • 2021-09-15
  • 2015-01-13
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多