Find each element that is less than some element to its right

后端 未结 6 1655
滥情空心
滥情空心 2021-01-12 03:05

I need to find elements of a vector that are less than one of more elements that come after it. It\'s easy to do in a loop:

x = some_vector_values;
for m = 1         


        
相关标签:
6条回答
  • 2021-01-12 03:40

    One-liner version

    comparisons = any(triu(bsxfun(@gt,x(:).',x(:))),2)
    
    0 讨论(0)
  • 2021-01-12 03:41

    This should be an algorithm that takes O(n) time and O(n) memory: Label the last element in your array the maximum element. Iterate backwards over the array. Whenever you have an element smaller than your maximum, save it. Otherwise, it becomes your new maximum. This should get you all of the elements you need with a single pass.

    0 讨论(0)
  • 2021-01-12 03:42

    This uses a divide-and-conquer approach (similar to binary search):

    1. Find the maximum of the vector.
    2. All elements to its left are accepted, whereas the maximum itself is rejected.
    3. For those elements to the right of the maximum, apply step 1.

    Although I haven't done a careful analysis, I think average complexity is O(n), or at most O(n log n). Memory is O(n).

    The result is a logical vector ind that contains true for accepted elements and false for rejected elements. The final result would be x(ind).

    x = [3 4 3 5 6 3 4 1];
    n = numel(x);
    ind = false(1,n); %// intiallization
    s = 1; %// starting index of the part of x that remains to be analyzed
    while s <= n %// if s > n we have finished
        [~, m] = max(x(s:end)); %// index of maximum within remaining part of x
        ind(s:s-2+m) = true; %// elements to its left are accepted
        s = s+m; %// update start of remaining part
    end
    

    Running time could be reduced a little by changing the while condition to while s < n, because the last element is always rejected.

    0 讨论(0)
  • 2021-01-12 03:59

    Your algorithm is so slow since if any(...)has to check n items on the first iteration, then n-1 items on the second iteration ... until checking a single item in the last iteration. Overal it thus has to do roughly n^2/2 comparisons, so its running time is quadratic as a function of the length of the input vector!

    One solution that is linear in time and memory might be to first calculate a vector with the maximum from that point until the end, which can be calculated in one backwards pass (you could call this a reversed cumulative maximum, which cannot be vectorized). After this, this vector is compared directly to x (untested):

    % calculate vector mx for which mx(i) = max(x(i:end))
    mx = zeros(size(x));
    mx(end) = x(end);
    for i = length(x)-1:-1:1 % iterate backwards
        mx(i) = max(x(i), mx(i+1));
    end
    
    for i = 1:length(x) - 1
        if mx(i) > x(i)
            do_such_and_such(i);
        end
    end
    

    In case you don't care about the order in which do_such_and_such is executed, these for loops can even be combined like so:

    mx = x(end);
    for i = length(x)-1:-1:1 % iterate backwards
        if x(i) < mx
            do_such_and_such(i);
        end
        mx = max(x(i), mx); % maximum of x(i:end)
    end
    
    0 讨论(0)
  • 2021-01-12 03:59

    If you would like to find elements that are less than some element to its right, you can do this also:

    x = some_values'; % x should be a column vector to use this
    h = hankel(x);
    m = max(h,[],2);
    f = find(x<m) %returns indices or f = (a<m) %returns true/false
    

    The hankel matrix will show the elements to the right as it goes down the rows.

    Then you can use the indices or true/false to iterate through a for loop and perform some operations. Here is an example:

    x =
    
         9
         8
        16
        16
         4
        10
         9
        13
        15
         1
    
    >> h = hankel(x)
    
    h =
    
         9     8    16    16     4    10     9    13    15     1
         8    16    16     4    10     9    13    15     1     0
        16    16     4    10     9    13    15     1     0     0
        16     4    10     9    13    15     1     0     0     0
         4    10     9    13    15     1     0     0     0     0
        10     9    13    15     1     0     0     0     0     0
         9    13    15     1     0     0     0     0     0     0
        13    15     1     0     0     0     0     0     0     0
        15     1     0     0     0     0     0     0     0     0
         1     0     0     0     0     0     0     0     0     0
    
    >> m = max(h,[],2)
    
    m =
    
        16
        16
        16
        16
        15
        15
        15
        15
        15
         1
    
    >> f = find(a<m)
    
    f =
    
         1
         2
         5
         6
         7
         8
    
    0 讨论(0)
  • 2021-01-12 04:04

    @NKN has it right. Sort.

    x = some_vector_values;  
    
    [Y,I]=sort(x);  %sort in order, get indices
    dy=gradient(Y); %get difference vector same size as input vector
    ind=find(dy~=0);%ignore places that are equal to the value of interest
    
    for m = 1 : length(ind)
        do_such_and_such to Y(ind(m));
    end
    

    Best of luck

    0 讨论(0)
提交回复
热议问题