C++ Vector Operations - c++

Is there any alternative for this? Performing a vector operation in multiples on certain condition?
i want to perform erase vector operation (n-1) times, just deleting only first element in a particular vector on a given if condition.
is it possible to do like this
if ( ret.size() == n ){
(n-1)*order.erase(order.begin());
(n-1)*quantity.erase(quantity.begin());
(n-1)*price.erase(price.begin());
}
I am currently doing this
if ( ret.size() == 2 ){
order.erase(order.begin());
quantity.erase(quantity.begin());
price.erase(price.begin());
}
if ( ret.size() == 3 ){
order.erase(order.begin());
order.erase(order.begin());
quantity.erase(quantity.begin());
quantity.erase(quantity.begin());
price.erase(price.begin());
price.erase(price.begin());
}

order.erase( order.begin(), order.begin() + ( ret.size() - 1 ) );
Needs prior checking of ret.size() vs. order.size() of course, but it seems your code can assert that from context.
That being said, when you are repeatedly erasing from the beginning of your vectors, perhaps your vectors are sorted the wrong way, or you might be better off with std::deque, performance-wise.
Edit: From the comments, it appears that your actual problem is "how to remove all but the last element of a vector". There are a number of ways to do this, like
// actually erasing all but the last
order.erase( order.begin(), order.end() - 1 );
...or...
// creating a new vector with the last element of the old
order = vector< ... >{ order.back() };
(The elipsis here standing for the type of your order vector, not the actual elipsis -- you will have to fill in that part.)

Related

how to get pairs of elements efficiently in a linked list (Haxe)

I have a list of objects and I would like to return each possible unique pair of objects within this list. Is the following the most efficient way to do that in Haxe?
for (elem1 in my_list)
{
for (elem2 in my_list)
{
if (elem1 == elem2)
{
break;
}
trace(elem1, elem2);
}
}
I would rather avoid the equality check if possible. The reason that I am not using arrays or vectors is that these lists will be added to/removed from very frequently and I have no need for index level access.
If you want to efficient (the less amount of iterations), you could loop like this:
for (i in 0 ... my_list.length-1) // loop to total minus 1
for (j in i+1 ... my_list.length) // start 1 further than i, loop to end
if (my_list[i] != my_list[j]) // not match
[my_list[i], my_list[j]]]; // make pair
Btw, it depends on the content if linked list or array actually faster, since this uses indexes now. You should test/measure it your case (don't assume anything if it's performance critic piece of code).
try online:
http://try.haxe.org/#2Ab3F

Assertion Error, using STL Vector

for(myIterator = numbers.begin();myIterator != numbers.end() ;myIterator++)
{
resultVect.push_back(*myIterator+2);
numbers.erase(myIterator+2);
}
numbers consist of a series of numbers (eg 1,2,3,4,5,6,7)
Then I would like to erase every 3rd number.
Something like,
1 2 3 4 5 6 ( First round -> 3 is out)
1 2 4 5 6 ( Second round -> 6 is out)
1 2 4 5 ( Third round -> 4 is out)
and so on.
I will store the number that goes out in another vector (resultVect).
Im getting Assertion error. Pls advise tq
When you use erase for a vector, it will relocate the elements after the erase position so the iterators after that will be invalidated.
Second when you say iterator + 2 and that could go beyond the range of the vector too.
Removing an element from the vector invalidates all iterators to that element and beyond (in the current standard, there is an open issue to change this).
The first question is how efficient you want the process to be, if you don't care (much) about performance you can do a simple loop:
for (int i = 3; i < input.size(); i+=3) {
result.push_back(input[i]);
}
for (int i = (input.size()+2)/3 - 1; i >= 0; --i) {
input.erase(input.begin()+i*3);
}
If performance is critical, you can take a look at the std::remove algorithm and use the same approach to avoid doing multiple copies of the elements while you run the algorithm. Basically you need a read and a write head into the original container and you only copy from the read to the write location if the condition is not met.
Simply put: you cannot modify a vector while iterating it. The iterator will become invalid and that will get you an assertion.
To properly do what you want, you might consider creating a copy of the vector with values to keep, and a vector with values to remove. Then replace the number vector by the one with the values to keep.

Finding the middle of an array without knowing the length

Find the middle of the string or array with an unknown length. You may
not traverse the list to find the length. You may not use anything to
help you find the length - as it is "unknown." (ie. no sizeof (C) or count(C#) etc...)
I had this question as an interview question. I'm just wondering what the answer is. I did ask if i could use sizeof, he said "no, the size of the string or array is unknown - you just need to get to the middle."
BTW, i'm not sure if this is actually possible to solve with no traversing. I almost felt as though he may have wanted to see how confident i am in my answer :S not sure...
His English was bad - also not sure if this contributed to misunderstandings. He directly told me that i do not need to traverse the list to get to the middle :S :S I'm assuming he meant no traversing at all..... :S
Have two counters, c1 and c2. Begin traversing the list, incrementing c1 every time and c2 every other time. By the time c1 gets to the end, c2 will be in the middle.
You haven't "traversed the list to find the length" and then divided it by two, you've just gone through once.
The only other way I can think of would be to keep taking off the first and last item of the list until you are left with the one(s) in the middle.
You (or your interviewer) are very vague in what the data is (you mentioned "string" and "array"); there's no assumption that can be made, so it can be anything.
You mentioned that the length of the string is unknown, but from your wording it might seem like you (or the interviewer) actually meant to say unknowable.
a) If it's just unknown, then the question is, how can it can be determined? In the case of strings, for example, you can consider the end to be '\0'. You can then apply some algorithms like the ones suggested by the other answers.
b) If it's unknowable, the riddle has no solution. The concept of middle has no meaning without a beginning and an end.
Bottom line, you cannot talk about a middle without a beginning and an end, or a length. Either this question was intentionally unanswerable, or you did not understand it properly. You must know more than just the beginning of the memory segment and maybe its type.
The following code will find the middle of an array WITHOUT traversing the list
int thearray[80];
int start = (int)&thearray;
int end = (int)(&thearray+1);
int half = ((end-start) / 4)/ 2;
std::cout << half << std::endl;
EDITS:
This code assumes you are dealing with an actual array and not a pointer to the first element of one, thus code like:
int *pointer_to_first_element = (int *)malloc(someamount);
will not work, likewise with any other notation that degrades the array reference into a pointer to the first element. Basically any notation using the *.
You would just use the difference between the addresses of the first and last elements.
I think this problem is aimed to also test your skills in problem analysis and requirements gathering. As others have stated before, we will need at least another piece of data to solve this issue.
My approach is to let clear to the interviewer that we can solve the problem with one constraint in the function call: the caller must provide 2 pointer, one to the beginning and another to the end of the array. Given those 2 pointers, and using basic pointer arithmetic, I reach this solution; please let me know what you think about it.
int *findMiddleArray( int const *first, int const *last )
{
if( first == NULL || last == NULL || first > last )
{
return NULL;
}
if( first == last )
{
return (int *)first;
}
size_t dataSize= ( size_t )( first + 1 ) - ( size_t )first,
addFirst= ( size_t )first,
addLast= ( size_t )last,
arrayLen= ( addLast - addFirst) / dataSize + 1,
arrayMiddle= arrayLen % 2 > 0 ? arrayLen / 2 + 1 : arrayLen / 2;
return ( int * )( ( arrayMiddle - 1 ) * dataSize + addFirst );
}
one way you can find midpoint of array is (for odd length array)
just use two loops ,1st loop start traverse from 0 index and the other (nested) loop will traverse from last index of array. Now just compare elements when it comes same ...that will be the mid point of array. i.e if(arr[i]== arr[j]) . Hope you got the point !
For Even length array ..you can do if(arr[i] == arr[j-1]) Or if(arr[i] == arr[j+1]) as they will never be same .try it by dry run!

vector constructor creating vector with one less element

I am trying to split a vector into "almost equal" parts, and create subvectors for those parts.
I have asked the original question here: How to split a vector into n "almost equal" parts but I found a really good solution, what I am trying to use, from here: Best way to extract a subvector from a vector?
I wrote this function for creating integers for start and end values (round is my function which rounds to specified digits.)
void split( double number, double parts )
{
double loop = number / parts;
for( int i = 0; i < parts; i++ )
{
int start = round( i * loop, 0 );
int end = round( ( i + 1 ) * loop - 1, 0 );
cout << start << " " << end << endl;
}
}
This function so far works OK, but my problem is that when I try to run this:
vector<some> dest( &source[start], &source[end] );
Then it creates one LESS element, then required. I mean for example if I call it with
vector<some> dest( &source[0], &source[99] );
then it will have 99 elements, instead of 100. Why is this happening?
How can I fix it? If I use [end+1], then it terminates at the last vector, with "subscript out of range."
The vector constructor (and all STL constructors that accept pointer ranges, for that matter) are designed to take in a range of STL-style iterators. When using iterators, you specify a range by providing a pointer to the first- and the past-the-end elements, not the first and last elements. If you wanted to create a vector as a copy of the subrange (0, 99) out of another vector, you could write
vector<some> dest(source.begin(), source.begin() + 100);
Note that this uses vector iterators to specify the slice of the first 100 elements rather than operator[], which has undefined behavior when the provided index is out of bounds. In your case, this undefined behavior is manifesting as a runtime debug error. Iterators don't have this problem, since they're specifically designed to be used this way.
If you want to use raw C++ arrays as input to the vector constructor, you could do it like this:
vector<some> dest(source, source + 100);
Hope this helps!
While it's not legal to use &v[n] if v is an std::vector with n elements you can use instead
vector<some> dest(v.begin()+first, v.begin()+last+1);
even if last+1 == n.

Solving the array sum problem using iterators and testing for equality only

While getting ready for interviews, I decided to code the classic "Find if there are two elements in an array that sum up to a given number" question using iterator logic, so that it can be generalized to other containers than vector.
Here's my function so far
// Search given container for two elements with given sum.
// If two such elements exist, return true and the iterators
// pointing to the elements.
bool hasElementSum( int sum, const vector<int>& v, vector<int>::iterator& el1, vector<int>::iterator& el2 )
{
bool ret = false;
el1 = v.begin();
el2 = v.end()-1;
while ( el1 != el2 ) {
if ( *el1 + *el2 == sum ) return true;
++el1;--el2;
}
return false;
}
This, of course, doesn't work, but I couldn't figure out a way to do it without using the condition while ( el1 >= el2 ). Various sources I looked advise against using omnly equality checking for iterators, to be able to generalize to all types of containers that support iterators.
Thanks!
First of all, your algorithm is wrong unless you've somehow determined ahead of time that you only need to look at sums where one item is in the first half of the collection, and the other is in the second half of the collection.
If the input's not sorted, then #sbi's answer is about as good as it gets.
With a sorted, random-access input, you can start with the first element, and do a binary search (or interpolation search, etc.) to see if you can find the value that would have to go with that to produce the desired sum. Then you can try the second element, but when you do the binary search (or whatever) use the result from the previous search as the upper limit. Since your first element is larger than the previous one, the matching value to produce the correct sum must be less than or equal to what you found the last time around.
foreach element1 in array
foreach element2 in array + &element1
if( element1 + element2 == sum )
return true
return false
This is O(N^2), since you have to add each element to each of the other elements.
Isn't this question usually asked with a sorted array ?
If not it has to work in O(n^2) complexity, and you will have to check all possible pairs.
I propose the following method though did not analyze the order
Construct a binary search tree with all the elements of the vector, Then for each element
foreach(element = vec.begin to vec.end)
{
if element == node.data, skip
if the element + node.data == sum, return true
if the element + node.data > sum, goto left child
if the element + node.data < sum, goto right child
}
Not a perfect solution/algorithm, but something of this kind.
Sorry, I screwed this one up. What I meant to write was a sort followed by a linear passed, which is the typical answer given to this question, as ltsik pointed out in his comment to Jerry, i.e. something like
bool hasElementSum( int sum, const vector<int>& v, int* ind1, int* ind2 )
{
*ind1 = 0; *ind2 = v.size()-1;
std::sort( v.begin(), v.end() );
while ( *ind1 <= *ind2 ) {
int s = v[*ind1] + v[*ind2];
if ( s > sum ) (*ind1)++;
else if ( s < sum ) (*ind2)++;
else return true
}
return false;
}
My question was how to write this using iterators without saying while (iter1 <= iter2 ) in order to be general, but I now see that doesn't make sense because this algorithm needs random access iterators anyway. Also, returning the indexes is meaningless since they refer to the sorted array and not the original one.