我在MATLAB中有以下类型的代码:
indices = find([1 2 2 3 3 3 4 5 6 7 7] == 3)
这将返回4,5,6-数组中元素的索引等于3。现在。我的代码使用很长的向量来执行此类操作。向量 总是被排序的 。
因此,我想要一个函数,用O(log n)代替find的O(n)复杂度,但必须对数组进行排序。
我知道ismember,但是据我所知,它不返回所有项目的索引,仅返回最后一个(我需要它们全部)。
出于可移植性的原因,我需要将解决方案设置为仅适用于MATLAB(无已编译的mex文件等)。
这是使用二进制搜索的快速实现。该文件也可以在github上找到
function [b,c]=findInSorted(x,range) %findInSorted fast binary search replacement for ismember(A,B) for the %special case where the first input argument is sorted. % % [a,b] = findInSorted(x,s) returns the range which is equal to s. % r=a:b and r=find(x == s) produce the same result % % [a,b] = findInSorted(x,[from,to]) returns the range which is between from and to % r=a:b and r=find(x >= from & x <= to) return the same result % % For any sorted list x you can replace % [lia] = ismember(x,from:to) % with % [a,b] = findInSorted(x,[from,to]) % lia=a:b % % Examples: % % x = 1:99 % s = 42 % r1 = find(x == s) % [a,b] = myFind(x,s) % r2 = a:b % %r1 and r2 are equal % % See also FIND, ISMEMBER. % % Author Daniel Roeske <danielroeske.de> A=range(1); B=range(end); a=1; b=numel(x); c=1; d=numel(x); if A<=x(1) b=a; end if B>=x(end) c=d; end while (a+1<b) lw=(floor((a+b)/2)); if (x(lw)<A) a=lw; else b=lw; end end while (c+1<d) lw=(floor((c+d)/2)); if (x(lw)<=B) c=lw; else d=lw; end end end