一尘不染

查找排序向量的更快版本(MATLAB)

algorithm

我在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文件等)。


阅读 297

收藏
2020-07-28

共1个答案

一尘不染

这是使用二进制搜索的快速实现。该文件也可以在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
2020-07-28