Say you have two integer vectors:
I would like to define a function that allows me to swap a range of elements among the two vectors passing start index and lenght of the two sequences as arguments.
For instance: where and are vectors and the numbers passed as arguments represents starting index and lenght of the sequences.
In this case I should get as autput
v1 = 1,2, 13,14,15 ,5,6,7,8,9
v2 = 10,11,12, 3,4 ,16,17,18
the signature of the function I defined as an example is not a constraint, if you think there is a better way it is ok
It appears that all the regular STL algorithms fall short of what you want to do exactly:
std::swap_ranges would be almost there, but it requires that you swap equally long ranges
std::rotate would also not be bad, but it requires that the end point of one range equals the begin point of the second range.
// pseudo-splice on vector
v1.insert(v1.begin() + 2 + 2, v2.begin() + 3, v2.begin() + 3 + 3);
v2.erase(v2.begin() + 3, v2.begin() + 3 + 3);
// pseudo-splice on vector
v2.insert(v2.begin() + 3, v1.begin() + 2, v1.begin() + 2 + 2);
v1.erase(v1.begin() + 2, v1.begin() + 2 + 2);
You can of course easily abstract this into a function template that takes arbitrary iterator boundaries for your two ranges.
Edit based on David's comment, you can do some optimization to avoid needless resizing
// compute smallest range here, in this case it's the v1 part
std::swap_ranges(v1.begin() + 2, v1.begin() + 2 + 2, v2.begin() + 3);
// now handle the remaining part of the longest range, in this case it's element v2 + 3 + 2
std::insert(v1.begin() + 2 + 2, v2.begin() + 3 + 2);
std::erase(v2.begin() + 3 + 2);
Update: it would be easier if you used std::list since then you could use splice (I rearranged the insert / erase part there to mimic the code below)
v1.splice(v1.begin() + 2 + 2, v2, v2.begin() + 3, v2.begin() + 3 + 3);
v2.splice(v2.begin() + 3, v1, v1.begin() + 2, v1.begin() + 2 + 2);
I think this shouldn't raise any difficulties besides the fact that you will have to re-assign the vectors if Length1 != Length2.
swap_elements(v1, start1, length1, v2, start2, length2){
if(length1 != length2){
//alloc mem for both of the arrays
//copy the unmodified portions of the original arrays into the new arrays
}
//swap the elements
}
Doing it in place with insert and erase has worse running time than the code below because each time insert and erase are called the other elements of the vector have to be moved accordingly in memory, and allocate new memory block, move vector elements to new memory block, if necessary. To avoid resizing and memory issues, it might be preferable to just create two new vector at the very beginning.
swap_elements(vector<int> &v1, int s1, int l1, vector<int> &v2, int s2, int l2){
vector<int> nv1(v1.begin(),v1.begin()+s1);
vector<int> nv2(v2.begin(),v2.begin()+s2);
for(int i=0;i<l2;i++)
nv1.push_back(v2[s2+i]);
for(int i=0;i<l1;i++)
nv2.push_back(v1[s1+i]);
for(int i=s1+l1+1;i<v1.size();i++)
nv1.push_back(v1[i]);
for(int i=s2+l2+1;i<v2.size();i++)
nv2.push_back(v2[i]);
v1.clear();
v2.clear();
v1=nv1;
v2=nv2;
}
Related
I'm trying to convert this function from recursive to iterations with stack but I can't figure out how and I keep failing
int F(int n)
{
if (n <= 1) return 1;
int a = n + F(n - 1);
cout << a << endl;
int b = n * F(n / 2);
int c = n - 2 - (a + b) % 2;
int d = F(c);
return a + b + d;
}
I tried to debug the code and break it down but luck was not on my side
edit:
these are the requirements
You are not allowed to use any built-in functions except those from: <cstdlib>, <cstdio>, <cstring>, <iostream> and <stack>.
You are not allowed to use string, vector, or anything from STL libraries except stack.
Moreover, I attempted to make multiple stack for each variable to store the results then substitute the answer but am still working on it.
Let's look at the single parts of the recursion:
We have f(n-1), f(n/2) and f(n-2-[0 or 1], no matter how big a or b might ever get. All these recursive calls fall back to a lower value.
First few values:
f(n) = 1; // n <= 1
f(2) = (2 + f(1)) + (2 * f(1)) + f(-1) // (c = 2 - 2 - 5 % 2)
= 6
f(3) = (3 + f(2)) + (3 * f(1)) + f(1) // (c = 3 - 2 - 12 % 2)
= 13
f(4) = (4 + f(3)) + (4 * f(2)) + f(1) // (c = 4 - 2 - 41 % 2)
= 42
f(5) = (5 + f(4)) + (5 * f(2)) + f(2) // (c = 5 - 2 - 77 % 2)
= 83
Obviously we can calculate a new value based on old ones – and if we calculate these first, we can simply look them up – apart from n == 2 where we'd get a negative lookup index. So we might initialise a std::vector with f(0), f(1) and f(2) (i.e. 1, 1, 6) and then iterate from 3 onwards until n calculating new values based upon the lookups of old ones:
if n <= 1:
return 1;
std::vector v({1, 1, 6});
if n >= v.size():
v.reserve(n + 1); // avoid unnecessary re-allocations
iterate i from v.size() up to n inclusive:
v.push_back(calculate, instead recursive calls look up in vector!);
return v[n];
Optimisation opportunity: If you retain results from previous calculations you don't need to re-calculate the values again and again (for the price of constantly instead of temporarily consuming quite a bit of memory!); all you have to do for is making the vector static:
static std::vector v({1, 1, 6});
// ^^^^^^
Edit – according to the edits of the question (referring to version 4):
As you are not allowed to use std::vector as proposed above instead allocate an array:
auto v = new unsigned int[std::max(3, n + 1)] { 1, 1, 6};
// I personally prefer unsigned int as negative values aren't possible anyway...
// calculate as with the vector
auto result = v[n];
delete[] v;
return result;
Keeping old values for future calls still is possible, but more complicated; you need to remember how large your array is and if n is greater than the size re-allocate a new array, copy values from old one to and delete the latter.
This approach keeps the requirements of the task as using std::stack is not explicitly requested... If that gets enforced then the algorithm won't change – solely the lookup gets pretty ugly; you need in addition to your main stack a temporary one to be able to backup the elements on top of those you want to lookup up:
// lookup the three values in DESCENDING order, each one
// as follows:
while(stack.size() > lookupIndex)
{
backup.push(stack.top());
stack.pop();
}
// now top elements have been moved away from main stack and
// backed up; the element to be looked up is moved, too;
// for illustration: consider lookupIndex == 0; what would be
// the main stack's size after popping the surplus elements???
lookupValue = backup().top();
// now as you have looked up all three values move the elements
// in the backup stack back to the main stack:
while(!backup.empty()) { /* analogously to above */ }
You can spare moving back if you are calculating the final value for n – unless you retain the main stack for future calls analogously to the static vector above (make it static analogously...).
Final note: I think more than anything else you can learn from this example how much additional effort – in coding and in runtime – you will load upon your shoulders if you chose a bad data structure compared to having chosen a suitable one...
Consider that
F(n) = 1 for all n <= 1, especially
F(0) = 1 and F(1) = 1
This is basically all you need to get the solution with a loop:
int F2(int n) {
std::vector<int> F{1,1};
for (int i=2;i <= n; ++i) {
int a = i + F[i-1];
int b = i * F[i/2];
int x = i-2-(a+b)%2; // might be negative
int d = x>0 ? F[x] : 1;
F.push_back(a+b+d);
}
return F.back();
}
I need to erase 2 ranges of elements from vector, the vector looks like this:
std::vector<int> vec {0, 1, 2, 3, 4, 5, 6, 7};
for example I need to keep only numbers 3 and 4. (in reality this could be big objects)
There are 2 options:
1) take target elements and drop the rest:
vec.assign(vec.begin() + 3, vec.begin() + 5);
2) explicitly remove ranges:
vec.erase(vec.begin() + 6, vec.end()); // first end (it's cheap)
vec.erase(vec.begin(), vec.begin() + 3); // then beginning (reallocates elements)
Which one of these 2 options will perform faster?
Or is there even better way?
You can use a single std::copy followed by std::vector::erase. It's correct and likely uses memcpy or memmove for POD types so it should be fast. Something like:
auto itr = std::copy(vec.begin() + 3, vec.begin() + 5, vec.begin());
vec.erase(itr, vec.end());
If the vector elements are movable you could use the std::move algorithm instead of std::copy.
There's array of size n. The values can be between 0 and (n-1) as the indices.
For example: array[4] = {0, 2, 1, 3}
I should say if there's any number that is repeated more than 1 time.
For example: array[5] = {3,4,1,2,4} -> return true because 4 is repeated.
This question has so many different solutions and I would like to know if this specific solution is alright (if yes, please prove, else refute).
My solution (let's look at the next example):
array: indices 0 1 2 3 4
values 3 4 1 2 0
So I suggest:
count the sum of the indices (4x5 / 2 = 10) and check that the values' sum (3+4+1+2+0) is equal to this sum. if not, there's repeated number.
in addition to the first condition, get the multiplication of the indices(except 0. so: 1x2x3x4) and check if it's equal to the values' multiplication (except 0, so: 3x4x1x2x0).
=> if in each condition, it's equal then I say that there is NO repeated number. otherwise, there IS a repeated number.
Is it correct? if yes, please prove it or show me a link. else, please refute it.
Why your algorithm is wrong?
Your solution is wrong, here is a counter example (there may be simpler ones, but I found this one quite quickly):
int arr[13] = {1, 1, 2, 3, 4, 10, 6, 7, 8, 9, 10, 11, 6};
The sum is 78, and the product is 479001600, if you take the normal array of size 13:
int arr[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
It also has a sum of 78 and a product of 479001600 so your algorithm does not work.
How to find counter examples?1
To find a counter example2 3:
Take an array from 0 to N - 1;
Pick two even numbers3 M1 > 2 and M2 > 2 between 0 and N - 1 and halve them;
Replace P1 = M1/2 - 1 by 2 * P1 and P2 = M2/2 + 1 by 2 * P2.
In the original array you have:
Product = M1 * P1 * M2 * P2
Sum = 0 + M1 + P1 + M2 + P2
= M1 + M1/2 - 1 + M2 + M2/2 + 1
= 3/2 * (M1 + M2)
In the new array you have:
Product = M1/2 * 2 * P1 + M2/2 * 2 * P2
= M1 * P1 * M2 * P2
Sum = M1/2 + 2P1 + M2/2 + 2P2
= M1/2 + 2(M1/2 - 1) + M2/2 + 2(M2/2 + 1)
= 3/2 * M1 - 2 + 3/2 * M2 + 2
= 3/2 * (M1 + M2)
So both array have the same sum and product, but one has repeated values, so your algorithm does not work.
1 This is one method of finding counter examples, there may be others (there are probably others).
2 This is not exactly the same method I used to find the first counter example - In the original method, I used only one number M and was using the fact that you can replace 0 by 1 without changing the product, but I propose a more general method here in order to avoid argument such as "But I can add a check for 0 in my algorithm.".
3 That method does not work with small array because you need to find 2 even numbers M1 > 2 and M2 > 2 such that M1/2 != M2 (and reciprocally) and M1/2 - 1 != M2/2 + 1, which (I think) is not possible for any array with a size lower than 14.
What algorithms do work?4
Algorithm 1: O(n) time and space complexity.
If you can allocate a new array of size N, then:
template <std::size_t N>
bool has_repetition (std::array<int, N> const& array) {
std::array<bool, N> rep = {0};
for (auto v: array) {
if (rep[v]) {
return true;
}
rep[v] = true;
}
return false;
}
Algorithm 2: O(nlog(n)) time complexity and O(1) space complexity, with a mutable array.
You can simply sort the array:
template <std::size_t N>
bool has_repetition (std::array<int, N> &array) {
std::sort(std::begin(array), std::end(array));
auto it = std::begin(array);
auto ne = std::next(it);
while (ne != std::end(array)) {
if (*ne == *it) {
return true;
}
++it; ++ne;
}
return false;
}
Algorithm 3: O(n^2) time complexity and O(1) space complexity, with non mutable array.
template <std::size_t N>
bool has_repetition (std::array<int, N> const& array) {
for (auto it = std::begin(array); it != std::end(array); ++it) {
for (auto jt = std::next(it); jt != std::end(array); ++jt) {
if (*it == *jt) {
return true;
}
}
}
return false;
}
4 These algorithms do work, but there may exist other ones that performs better - These are only the simplest ones I could think of given some "restrictions".
What's wrong with your method?
Your method computes some statistics of the data and compares them with those expected for a permutation (= correct answers). While a violation of any of these comparisons is conclusive (the data cannot satisfy the constraint), the inverse is not necessarily the case. You only look at two statistics, and these are too few for sufficiently large data sets. Owing to the fact that the data are integer, the smallest number of data for which your method may fail is larger than 3.
If you are searching duplicates in your array there is simple way:
int N =5;
int array[N] = {1,2,3,4,4};
for (int i = 0; i< N; i++){
for (int j =i+1; j<N; j++){
if(array[j]==array[i]){
std::cout<<"DUPLICATE FOUND\n";
return true;
}
}
}
return false;
Other simple way to find duplicates is using the std::set container for example:
std::set<int> set_int;
set_int.insert(5);
set_int.insert(5);
set_int.insert(4);
set_int.insert(4);
set_int.insert(5);
std::cout<<"\nsize "<<set_int.size();
the output will be 2, because there is 2 individual values
A more in depth explanation why your algorithm is wrong:
count the sum of the indices (4x5 / 2 = 10) and check that the values' sum (3+4+1+2+0) is equal to this sum. if not, there's repeated number.
Given any array A which has no duplicates, it is easy to create an array that meets your first requirement but now contains duplicates. Just take take two values and subtract one of them by some value v and add that value to the other one. Or take multiple values and make sure the sum of them stays the same. (As long as new values are still within the 0 .. N-1 range.) For N = 3 it is already possible to change {0,1,2} to {1,1,1}. For an array of size 3, there are 7 compositions that have correct sum, but 1 is a false positive. For an array of size 4 there are 20 out of 44 have duplicates, for an array of size 5 that's 261 out of 381, for an array of size 6 that's 3612 out of 4332, and so on. It is save to say that the number of false positives grows much faster than real positives.
in addition to the first condition, get the multiplication of the indices(except 0. so: 1x2x3x4) and check if it's equal to the values' multiplication (except 0, so: 3x4x1x2x0).
The second requirement involves the multiplication of all indices above 0. It is easy to realize this is could never be a very strong restriction either. As soon as one of the indices is not prime, the product of all indices is no longer uniquely tied to the multiplicands and a list can be constructed of different values with the same result. E.g. a pair of 2 and 6 can be replaced with 3 and 4, 2 and 9 can be replaced with 6 and 3 and so on. Obviously the number of false positives increases as the array-size gets larger and more non-prime values are used as multiplicands.
None of these requirements is really strong and the cannot compensate for the other. Since 0 is not even considered for the second restriction a false positive can be created fairly easy for arrays starting at size 5. any pair of 0 and 4 can simply be replaced with two 2's in any unique array, for example {2, 1, 2, 3, 2}
What you would need, is to have a result that is uniquely tight to the occurring values. You could tweak your second requirement to a more complex approach and skip over the non-prime values and take 0 into account. For example you could use the first prime as multiplicand (2) for 0, use 3 as multiplicand for 1, 5 as multiplicand for 2, and so on. That would work (you would not need the first requirement), but this approach would be overly complex. An simpler way to get a unique result would be to OR the i-th bit for each value (0 => 1 << 0, 1 => 1 << 1, 2 => 1 << 2, and so on. (Obviously it is faster to check wether a bit was already set by a reoccurring value, rather than wait for the final result. And this is conceptually the same as using a bool array/vector from the other examples!)
Which is the smartest way to add at the beggining of a vector the last two elements of the vector itself and add at the end of the vetor the first two element of the vector?
I mean, if my starting vector is
v = 1 2 3 4 5 6 7 8 9
I need that it becames
v = 8 9 1 2 3 4 5 6 7 8 9 1 2
First, if the container is going to be large then consider using deque instead of vector. It's more efficient for adding at the start.
For vector you can't insert elements out of the vector to the start because the first thing that happens is everything in the vector gets moved (and all iterators and references to those elements are invalidated). So you either need to copy the elements out of the vector or you need to put insert elements at the start and then copy-assign to them. Assuming the type is int, I'll go with the former:
if (v.size() >= 2) {
int tmp[] = {*(v.end() - 2), *(v.end() - 1)};
v.insert(v.begin(), tmp, tmp + 2);
tmp[0] = v[2]; tmp[1] = v[3];
v.insert(v.end(), tmp, tmp + 2);
}
Alternatively, this uses more memory but might be easier to read. As a bonus it gives the strong exception guarantee even with types whose copy constructor can throw. My code above can be made to offer the strong guarantee by adding a call to reserve, but only because int is a trivial type:
if (v.size() >= 2) {
std::vector<int> new_v;
new_v.reserve(v.size() + 4);
new_v.insert(new_v.end(), v.end() - 2, v.end());
new_v.insert(new_v.end(), v.begin(), v.end());
new_v.insert(new_v.end(), v.begin(), v.begin() + 2);
v.swap(new_v);
}
For deque you don't need to store any elements outside the container provided you use a reference instead of an iterator to access them. Again this only offers the basic exception guarantee.
if (v.size() >= 2) {
v.push_front(v.back());
v.push_front(*&(v.end() - 1));
v.push_back(*&(v.begin() + 2));
v.push_back(*&(v.begin() + 3));
}
My five cents
std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
v.insert( v.end(), { v[0], v[1], v[v.size() - 2], v[v.size() - 1] } );
std::rotate( v.begin(), std::prev( v.end(), 2 ), v.end() );
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
By using the vector::insert function for ranges. It is easier to first insert the first two elements at the end.
v.insert(v.end(), v.begin(), v.begin()+2);
v.insert(v.begin(), v.end()-2, v.end());
Edit:
Is undefined behaviour.
Appending std::vector to itself, undefined behavior?
An interview question:
Given two non-ordered integer sequences a and b, their size is n, all
numbers are randomly chosen: Exchange the elements of a and b, such that the sum of the elements of a minus the sum of the elements of b is minimal.
Given the example:
a = [ 5 1 3 ]
b = [ 2 4 9 ]
The result is (1 + 2 + 3) - (4 + 5 + 9) = -12.
My algorithm: Sort them together and then put the first smallest n ints in a and left in b. It is O(n lg n) in time and O(n) in space. I do not know how to improve it to an algorithm with O(n) in time and O(1) in space. O(1) means that we do not need more extra space except seq 1 and 2 themselves.
Any ideas ?
An alternative question would be: What if we need to minimize the absolute value of the differences (minimize |sum(a) - sum(b)|)?
A python or C++ thinking is preferred.
Revised solution:
Merge both lists x = merge(a,b).
Calculate median of x (complexity O(n) See http://en.wikipedia.org/wiki/Selection_algorithm )
Using this median swap elements between a and b. That is, find an element in a that is less than median, find one in b that is more than median and swap them
Final complexity: O(n)
Minimizing absolute difference is NP complete since it is equivalent to the knapsack problem.
What comes into my mind is following algorithm outline:
C = A v B
Partitially sort #A (number of A) Elements of C
Subtract the sum of the last #B Elements from C from the sum of the first #A Elements from C.
You should notice, that you don't need to sort all elements, it is enough to find the number of A smallest elements. Your example given:
C = {5, 1, 3, 2, 4, 9}
C = {1, 2, 3, 5, 4, 9}
(1 + 2 + 3) - (5 + 4 + 9) = -12
A C++ solution:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
// Initialize 'a' and 'b'
int ai[] = { 5, 1, 3 };
int bi[] = { 2, 4, 9 };
std::vector<int> a(ai, ai + 3);
std::vector<int> b(bi, bi + 3);
// 'c' = 'a' merged with 'b'
std::vector<int> c;
c.insert(c.end(), a.begin(), a.end());
c.insert(c.end(), b.begin(), b.end());
// partitially sort #a elements of 'c'
std::partial_sort(c.begin(), c.begin() + a.size(), c.end());
// build the difference
int result = 0;
for (auto cit = c.begin(); cit != c.end(); ++cit)
result += (cit < c.begin() + a.size()) ? (*cit) : -(*cit);
// print result (and it's -12)
std::cout << result << std::endl;
}