I'm trying to iterate a vector from the nth element onwards. Not sure how should i go about doing this.
I have a vector A and B. My vector A has 10 elements of PC1-PC10 and my vector B has 20 elements of User1-User20.
So what I want to do is that when both my vector A and B reaches the 10th element, meaning to say the last element for vector A, I want to repeat iterating vector A but start iterating vector B from the 11th element so that I can do some stuff with it.
Below is the simplified code that I came up with but technically its about the same thing:
vector<string>::iterator b = vecB.begin();
for (int i = 1; i < 2; i++) {
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
if (a == vecA.end()) {
b = vecB.begin() + 10; //here the iterator for verB should start from the 11th element
}
++b
}
}
Should I mess with the iterator for vector B? Or is there another alternative?
EDIT
It seems that I have been asking the wrong question after all. I have marked the answer to this question and will be posting another shortly. Thanks for the quick response to my question!
The if condition inside the nested loop will never be true, because it conflicts with the loop condition:
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
// This check ----------------------------------^^^^^^^^^^^^^^^
// guarantees that this will never succeed:
// vvvvvvvvvvvvvvv
if (a == vecA.end()) {
...
}
}
You should rewrite the code like this:
vector<string>::iterator b = vecB.begin();
// Check that vecB has sufficient number of elements before entering the loop.
for (int i = 1 ; i < 2 ; i++) {
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; ++a, ++b) {
...
}
// At this point we know for sure that a == vecA.end(),
// because it is a post-condition of the for loop above.
b = std::next(vecB.begin(), 11);
}
The call of ++b can be moved into the loop header.
Note the use of std::next: although
b = vecB.begin() + 10;
compiles for vectors, it is not guaranteed for all kinds of containers. Use std::next instead:
b = std::next(vecB.begin(), 11);
Note: This code makes an assumption that vecB has at least 11 elements more than vecA does. This may be OK if you check that assumption before entering the loop. If this assumption is broken, the code would have undefined behavior.
Others have already answered how to reset or advance an iterator, so I'll just answer, how to solve your problem in a simpler way. It's much simpler to iterate two vectors in parallel using the index rather than two iterators:
// assumes vecB is bigger than vecA as described in the question
for (std::size_t i = 0; i < vecB.size(); i++) {
auto user = vecB[i];
auto pc = vecA[i % vecA.size()];
}
Pay attention to how the smaller vector is iterated using the remainder operator.
In addition to using std::next, as shown in the answer by #dasblinkenlight, you can also use std::advance.
b = vecB.begin();
std::advance(b, 10);
You don't need to change the iterator for B, it will automatically continue with 11th element. But you need to restart iteration on A at the beginning of the for loop (or you would work with a.end() which is not a valid element):
if (a == vecA.end()) {
a = vecA.begin();
}
Also you should iterate over both but check for end on b only; if you check on a, the for would end before the if would turn true:
for (auto a = vecA.begin(), b = vecB.begin(); b != vecB.end(); ++a, ++b)
You can see the whole code here.
I actually prefer to manually iterate over vectors pre-C++11 because it looks way cleaner and more readable than iterators:
for (unsigned int i = 0; i < my_vector.size(); i++) {
my_vector[i]; //Do Something
}
You can specify the range you want to iterate over simply by modifying the for loop conditional (i.e. unsigned int i = n)
Edit: Before downvoting actually read my entire answer. Using iterators on vectors is overly verbose and makes your code virtually unreadable. If there is a legitimate reason this method should not be used in favor of iterators, then please leave a comment.
Most people aren't looking for an ultra-generic, drop-in-any-container solution. Most people know they need a dynamic list, vector fits the bill, so why not make your code easy to read for the next guy?
Related
I was trying to solve this problem on leet code it works fine on my vs code and gcc compiler but i'm getting this
Runtime error: Address sanitizer Heap buffer Overflow error message with a long list of address or something on the website. Help me fix it. Here's the code
class Solution
{
public:
char nextGreatestLetter(vector<char> v, char a)
{
int l=v.size()-1;
if (v[l] < a)
{
return v[0];
}
int i = 0;
while (v[i] <= a)
{
i++;
}
return v[i];
}
};
p.s the array is sorted in ascending order
This code snippet has a lot of problems:
The while loop isn't guaranteed to terminate. If the last character of v is == a, then the first v[l] < a test will be false, but v[i] <= a might be true all the way through the array (it looks like v is meant to be pre-sorted into ascending order), which will have you eventually accessing v[i] for a value of i >= v.size(). That is an illegal/undefined array access and might be the source of the error message you report, if the test platform had strict bounds-checking enabled.
The logic of returning v[0] if a is greater than any character in v (again, inferring from the loop that v is supposed to be pre-sorted into ascending order) also seems flawed. Why not return the value of a instead? The caller can easily see that if the return value was <= a, then there clearly was no element of v greater than a.
It's almost certainly worth your time to handle cases where the passed-in v array is empty (v.size() == 0) or not actually pre-sorted, i.e. by caching n = v.size() and changing the loop condition to while (i < n && v[i] <= a). Don't let fragile functions creep into your codebase!
Recently I came across this code fragment:
// look for element which is the smallest max element from
// a given iterator
int diff = std::numeric_limits<int>::max();
auto it = nums.rbegin();
auto the_one = nums.rbegin();
for (; it != given; ++it) // this terminates
{
int local_diff = *it - *given;
// if the element is less than/equal to given we are not interested
if (local_diff <= 0)
continue;
if (local_diff < diff)
{
// this update the global diff
diff = local_diff;
the_one = it;
}
}
I was wondering if anyone can think of an elegant stl algorithm to replace the above. Essentially we have to go through all the elements, and also keep track of the one which we need. This is not similar to std::max_element (atleast I can't model it that way).
auto the_one = std::min_element(nums.rbegin(), given,
[given](int a, int b) {
bool good_a = a > *given;
bool good_b = b > *given;
return (good_a && good_b) ? a < b : good_a;
});
The trick is to write a comparison function that declares any "good" element (one that's greater than *given) to compare smaller than any "not good" element. Two "good" elements are compared normally; two "bad" elements are always declared equivalent.
Create a function that checks whether an array has two opposite elements or not for less than n^2 complexity. Let's work with numbers.
Obviously the easiest way would be:
bool opposite(int* arr, int n) // n - array length
{
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
if(arr[i] == - arr[j])
return true;
}
}
return false;
}
I would like to ask if any of you guys can think of an algorithm that has a complexity less than n^2.
My first idea was the following:
1) sort array ( algorithm with worst case complexity: n.log(n) )
2) create two new arrays, filled with negative and positive numbers from the original array
( so far we've got -> n.log(n) + n + n = n.log(n))
3) ... compare somehow the two new arrays to determine if they have opposite numbers
I'm not pretty sure my ideas are correct, but I'm opened to suggestions.
An important alternative solution is as follows. Sort the array. Create two pointers, one initially pointing to the front (smallest), one initially pointing to the back (largest). If the sum of the two pointed-to elements is zero, you're done. If it is larger than zero, then decrement the back pointer. If it is smaller than zero, then increment the front pointer. Continue until the two pointers meet.
This solution is often the one people are looking for; often they'll explicitly rule out hash tables and trees by saying you only have O(1) extra space.
I would use an std::unordered_set and check to see if the opposite of the number already exist in the set. if not insert it into the set and check the next element.
std::vector<int> foo = {-10,12,13,14,10,-20,5,6,7,20,30,1,2,3,4,9,-30};
std::unordered_set<int> res;
for (auto e : foo)
{
if(res.count(-e) > 0)
std::cout << -e << " already exist\n";
else
res.insert(e);
}
Output:
opposite of 10 alrready exist
opposite of 20 alrready exist
opposite of -30 alrready exist
Live Example
Let's see that you can simply add all of elements to the unordered_set and when you are adding x check if you are in this set -x. The complexity of this solution is O(n). (as #Hurkyl said, thanks)
UPDATE: Second idea is: Sort the elements and then for all of the elements check (using binary search algorithm) if the opposite element exists.
You can do this in O(n log n) with a Red Black tree.
t := empty tree
for each e in A[1..n]
if (-e) is in t:
return true
insert e into t
return false
In C++, you wouldn't implement a Red Black tree for this purpose however. You'd use std::set, because it guarantees O(log n) search and insertion.
std::set<int> s;
for (auto e : A) {
if (s.count(-e) > 0) {
return true;
}
s.insert(e);
}
return false;
As Hurkyl mentioned, you could do better by just using std::unordered_set, which is a hashtable. This gives you O(1) search and insertion in the average case, but O(n) for both operations in the worst case. The total complexity of the solution in the average case would be O(n).
I have stl vector consisting of several elements. I need to iterate through this vector and delete elements which meets some criteria. So I wrote this code
for (int j = imageDataVector.size()-1; j >= 0; j--) {
if(imageDataVector[i] < threshold)
imageDataVector.erase(imageDataVector.end() - j);
}
This code works fine for almost all cases, however if all elements of vector meets the criteria I get an error:
vector erase iterator outside the range
This error occurs if I have only one element left in the vector. What do I do wrong ?
if(imageDataVector[i] < threshold)
imageDataVector.erase(imageDataVector.end()-j);
Should likely be:
if(imageDataVector[j] < threshold)
imageDataVector.erase(imageDataVector.begin()+j);
EDIT: for completeness, the erase-remove way and the iterator way:
imageDataVector.erase(std::remove_if(imageDataVector.begin(), imageDataVector.end(), std::bind2nd(std::less<vector_data_type>(), threshold)), imageDataVector.end());
vector<type>::iterator it = imageDataVector.begin();
while (it != imageDataVector.end()) {
if (*it < threshold)
it = imageDataVector.erase(it);
else
++it;
}
You're mixing forward and backward indexing.
I'd consider using std::remove_if instead. That way if you're removing multiple elements you don't shift the entire vector forwards on each erase.
It would look something like this:
imageDataVector.erase(std::remove_if(imageDataVector.begin(), imageDataVector.end(), std::bind2nd(std::less<data_type>(), threshold)), imageDataVector.end());
Alternately try the following, noting that it will result in a lot of movement if you remove multiple items from the vector.
for (int j=imageDataVector.size()-1 ;j>=0;j--)
{
if(imageDataVector[i] < threshold)
imageDataVector.erase(imageDataVector.begin()+j);
}
You're trying to count down j to zero, and imageDataVector.end() - 0 is not a valid iterator. In the standard C++ library containers, the end iterator points one past the last element, not at the last element.
for (int i = 0 ; i < stlVector.size() ; i++)
{
if (i == 10)
{
stlVector.erase(stlVector.begin() + 5 )
}
}
Does the termination condition part "stlVector.size()" take "stlVector.erase(...)"
into consideration? In other word does stlVector.size() refresh for every loop iteration?
I can't test it right now, so i posted a question here.
Thx in advance!
Best regards,
zhengtonic
Just to be clear, don't think of it in terms of the loop refreshing anything. Every time the condition is checked (at the start of each time through the loop), the size() method is called on the stlVector variable, and the current size of the vector is returned.
The erase() method reduces the size of the vector, so the next time size() is called, the returned value will be smaller.
Yes it does!
stlVector.size () // is called for evey iteration
Thus for every loop you'll have the test "i < stlVector.size ()" re-evaluate!
Yes, the test is performed, with side effects, for each loop.
A for loop is merely a nice convention - a for loop is easily decomposed as a while loop:
for (int i = 0 ; i < stlVector.size() ; i++)
{
if (i == 10)
{
stlVector.erase(stlVector.begin() + 5 )
}
}
Becomes:
int i = 0 ;
while(i < stlVector.size())
{
if (i == 10)
{
stlVector.erase(stlVector.begin() + 5 )
}
i++;
}
-Adam
Yes, it does, but don't do this! If you want to remove elements from a vector, do it inside another loop. You are deleting elements after the i index in this case: nothing guarantees that the stlVector[i+5] element exists. If you remove the i-th element from the vector, your count is broken because you can jump elements without checking them.
The most safe way of doing this is storing references for the elements on the stlVector you want to delete on another vector, and then iterate on this auxiliar vector doing stlVector.erase(auxVector[i]).
I expect the code you provided is just "fantasy code" (as one commenter put it) to give a concrete example of the type of thing you're trying to do.
However just in case it's not: the loop you gave will skip over the 12th element (i.e. the element originally in stlVector[11]) because when examining stlVector[10] you delete an earlier element, causing all later elements to shunt forward one position, but you still increment i at the end of the loop. So the next iteration will look at stlVector[11] which is actually the element that was originally in stlVector[12]. To remedy this, you need to --i after the call to erase().
Always reevaluate sure!
Also, to clarify a bit, since you asked if it's done this way "in VC++ 6".
The "continue condition" is re-evaluate on every loop in EVERY version of C, C++, C# and Java.
If any complier does not generate code which does that, it is broken, and must be avoided.
As others have said, yes the condition is re-evaluated each time through the loop. That's why a common performance optimization is:
int saveSize = someExpensiveComputation();
for (int i = 0 ; i < saveSize ; i++)
{
foo(i);
}
where the loop conditional is at all expensive to compute, instead of
for (int i = 0 ; i < someExpensiveComputation(); i++)
{
foo(i);
}
Where the expensive computation is needlessly done each iteration through the loop.
Yes it reduces the size. More information is here