C++ How to find position of last occurrence of element in vector

Viewed 2230

Let's say I have a vector with the numbers: 10 10 58 31 63 40 76. I want to find the position of the last occurrence of the minimum element. The minimum element is 10. The position of the last occurrence of 10 is 1.

I've tried using reverse iterators, but I'm still a little bit confused.

7 Answers

Assuming the vector:

std::vector<int> v = { 10, 10, 58, 31, 63, 40, 76 };

You can get the last minimum element using reverse iterators and std::min_element:

auto last_min = std::min_element(std::rbegin(v), std::rend(v));

Then get the distance from the beginning of the vector using std::distance and the "base" of the reverse iterator:

auto last_min_distance = std::distance(std::begin(v), last_min.base());

Finally subtract one to get the index:

auto last_min_index = last_min_distance - 1;

Your idea with the reverse iterator was the right thing to do. First you need to find the last element. This can be done with std::min_element and reverse iterators:

auto min_elem_iter = std::min_element(std::crbegin(vec), std::crend(vec));

where vec is the std::vector you want to search through.

Now you have an iterator to the last element you searched. You need to check if it is the same as std::crend(vec) to make sure it points to a valid element.

If you want to know the index, you need std::distance, which can be used to calculate the distance between two iterators. With that you can find out the distance between std::crbegin(vec) and the iterator which points to the element we found. This can than be used together with the size of the vector to calculate the index.

So all in all you can get what you want with:

template<class T>
auto getIndexOfLastMin(const std::vector<T>& vec)
    -> std::optional<std::size_t>
{
    auto last_elem_iter = std::min_element(std::crbegin(vec), 
                                           std::crend(vec));
    if(last_elem_iter == std::crend(vec)){
        return std::nullopt;
    }
    
    auto idx = std::distance(std::rbegin(vec), last_elem_iter);
    return static_cast<std::size_t>(vec.size() -1 - idx);
}

You can checkout and run the code here

let's say minimum element is k

for (int i = 0; i < vector.size(); i++)
{
      if( k == vector[i])
      {
         index = i;
      }
}

At the end of the loop, index would be the last position of the minimum element in vector.

... And if you haven't found the minimum element up front, you can do:

int min_element = std::numeric_limits <int>::max;
size_t index = 0;

for (size_t i = 0; i < vector.size(); i++)
{
    if (vector[i] <= min_element)
    {
        min_element = vector[i];
        index = i;
    }
}

Not everything has to be sophisticated (& this is the main pitfall of Modern C++: Any programmer tries to be a genius). Keep it simple:

#include <vector>
#include <limits.h>

int main()
{
    std::vector<int> v = { 10, 10, 58, 31, 63, 40, 76 }; // This is the vector
    
    int min = INT_MAX;
    size_t i = 0, last_min_i = 0;

    for (auto item : v) {
        if (item <= min) {
            min = item;
            last_min_i  = i;
        }
        i++;
    }

    // last_min_i  holds the result
}

I'm assuming that you've already found the minimum element. Then a simple backwards loop seems easiest

size_t index = vec.size();
do
{
    --index;
}
while (vec.at(index) != min_element);

If by chance you've made a mistake then using at will result in an exception, that's a bit safer than the UB you'd get if you used [].

You could do something with reverse iterators but why complicate?

To find out the last occurrence of an element in a vector, we could use find_end(). It is used to find out the subsequence's last occurrence.

vector<int> v1 = {1,3,5,7,9};
vector<int> v2 = {7};
auto it = find_end(v1.begin(),v1.end(),v2,begin(),v2.end());

//printing the position of the element, use it-v1.begin();
Related