簡體   English   中英

對於X中的每個元素,找到最大的索引,而不是在Y中

[英]For each element in X find index of largest without going over in Y

我正在尋找一種方法來改善以下算法的性能。 給定兩個數組X和Y.

對於X的每個元素,找到Y中最大值的索引,該索引不超過X中元素的值。可以安全地假設X和Y單調遞增(排序)並且Y(1)小於每個X中的值.X也通常遠大於Y.

作為一個例子,給出以下內容。

X = [0.2, 1.5, 2.2, 2.5, 3.5, 4.5, 5.5, 5.8, 6.5];
Y = [0.0, 1.0, 3.0, 4.0, 6.0];

我希望輸出是

idx = [1, 2, 2, 2, 3, 4, 4, 4, 5]

我提出的最快的方法是下面的函數,它無法利用列表進行排序並使用for循環來逐步遍歷其中一個數組的事實。 這提供了一個有效的解決方案,但在我使用此功能的實驗中,在分析所需的總共30分鍾內花費了將近27分鍾。

function idx = matchintervals(X,Y)
  idx = zeros(size(X));
  for i = 1:length(Y)-1
    idx(X >= Y(i) & X < Y(i+1)) = i;
  end
  idx(X >= Y(end)) = length(Y);
end

任何幫助是極大的贊賞。

如果您正在尋找最快的解決方案,它可能最終成為一個簡單的while循環(這樣可以利用數組排序的事實):

X = [0.2, 1.5, 2.2, 2.5, 3.5, 4.5, 5.5, 5.8, 6.5];
Y = [0.0, 1.0, 3.0, 4.0, 6.0];

xIndex = 1;
nX = numel(X);
yIndex = 1;
nY = numel(Y);
index = zeros(size(X))+nY;  % Prefill index with the largest index in Y

while (yIndex < nY) && (xIndex <= nX)
  if X(xIndex) < Y(yIndex+1)
    index(xIndex) = yIndex;
    xIndex = xIndex+1;
  else
    yIndex = yIndex+1;
  end
end

>> index

index =

     1     2     2     2     3     4     4     4     5

此循環將迭代最大numel(X)+numel(Y)-1次,如果X中有許多值大於Y的最大值,則可能更少。

時間:我用評論中的樣本數據運行了一些時間。 以下是從最快到最慢排序的結果:

X = 1:3:(4e5);
Y = 0:20:(4e5-1);

% My solution from above:
tElapsed =
   0.003005977477718 seconds

% knedlsepp's solution:
tElapsed =
   0.006939387719075 seconds

% Divakar's solution:
tElapsed =
   0.011801273498343 seconds

% H.Muster's solution:
tElapsed =
   4.081793325423575 seconds

單行,但可能比gnovice的解決方案慢:

idx = sum(bsxfun(@ge, X, Y'));

使用sort和幾個masks -

%// Concatenate X and Y and find the sorted indices
[sXY,sorted_id] = sort([X Y]);

%// Take care of sorted_id for identical values between X and Y
dup_id = find(diff(sXY)==0);
tmp = sorted_id(dup_id);
sorted_id(dup_id) = sorted_id(dup_id+1);
sorted_id(dup_id+1) = tmp;

%// Mask of Y elements in XY array
maskY = sorted_id>numel(X);

%// Find island lengths of Y elements in concatenated XY array
diff_maskY = diff([false maskY false]);
island_lens = find(diff_maskY ==-1) - find(diff_maskY ==1);

%// Create a mask of double datatype with 1s where Y intervals change
mask_Ys = [ false maskY(1:end-1)];
mask_Ysd = double(mask_Ys(~maskY));

%// Incorporate island lengths to change the 1s by offsetted island lengths
valid = mask_Ysd==1;
mask_Ysd(valid) = mask_Ysd(valid) + island_lens(1:sum(valid)) - 1;

%// Finally perform cumsum to get the output indices
idx = cumsum(mask_Ysd);

我有與Divakar類似的想法。 這基本上使用穩定sortY的值之后找到X值的插入點。 需要對XY進行排序才能正常工作!

%// Calculate the entry points
[~,I] = sort([Y,X]);
whereAreXs = I>numel(Y);
idx = find(whereAreXs)-(1:numel(X));

您可以通過以下方式查看X的值和不超過X值的Y的相應值:

%%// Output:
disp([X;Y(idx)]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM