简体   繁体   中英

Prime factorization of number error

I made a function that returns a vector with all the prime factors of an integer, and I am trying to make another function that creates a map from that vector .

However, I am getting some typicall illegal memory access error and I cannot find what it is. I think it happens inside the for loop of the map<int, int> factorizacion(vector<int>) function.

I hope I could get some help here.

I could post the whole program but I'll just stick to the function that's causing the issue. Just ask for the rest of the code in case you need to give it a look.

map<int, int> factorizacion(vector<int> v) {
    map<int, int> m;

    while (!v.empty()) {
        int elto = v.front();
        int ctd = 0;

        for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
            if (*it == elto) {
                ++ctd;
                v.erase(it);
            }
        }
        m[elto] = ctd;
    }

    return m;
}

You modify a collection you iterate upon:

for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
    if (*it == elto) {
        ++ctd;
        v.erase(it);
    }
}

If you erase the item pointed by the iterator you can not just continue using the same iterator.

Btw you can make use of the fact that map will automatically initialize to 0 a value for key that does not exist.

This code will do what you want:

map<int, int> m;
for (int i = 0; i < v.size(); i++) {
  m[v[i]]++;
}

The only thing is that performance-wise my solution is a bit slower - it executes more queries than the optimal solution. However, the solution I propose is better that yours (when it gets fixed, because):

  • Erasing in a vector is costly operation and takes linear time, a lot worse performance wise than my map tweak
  • I do not alter the parameter of the method. I know it is not passed in by reference but it is always a good idea not to affect parameters when this is possible.

v.erase(it) makes it invalid. You need to change your loop:

for (vector<int>::iterator it = v.begin(); it != v.end();) {
    if (*it == elto) {
        ++ctd;
        it = v.erase(it);
    } else {
       ++it;
    }
}

Or better, use std::remove and .erase similarly to the "erase-remove" idiom. Which I won't repeat here because you can look it up. You can compute the count as the difference between two iterators.

Or even better, count the factors without erasing them at all, as in Niklas's comment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM