Shifting values of a vector in C++ - c++

Assuming the following basic vector:
std::vector<int> numbers;
numbers.push_back(0);
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
What is an efficient way to insert 6 new numbers in between 0 and 1?
Here is my approach right now, but I feel like it's not very efficient:
for (int new_number=0;new_number<6;new_number++) {
numbers.emplace(numbers.begin()+1+new_number,new_number);
}
The reason I don't like this approach is that numbers 1-3 have to be moved 6 times. Is there a way to move these numbers just once instead of doing it 6 times? Then I can use this loop:
for (int new_number=0;new_number<6;new_number++) {
numbers[new_number+1]=new_number;
}
Here is what I am trying to accomplish:
Vector Before Shifting:
0 1 2 3
Vector After Shifting:
0 X X X X X X 1 2 3

There is an overload of the insert function that lets you insert n identical items:
// Add six copies of -1 to the vector starting at position 1
numbers.insert(numbers.begin()+1, 6, -1);
You can use another overload that takes three iterators - the iterator where to insert, and a begin/end pair of iterators from where to take the data:
// Insert addedNUmbers at position 1
numbers.insert(numbers.begin()+1, addedNUmbers.begin(), addedNUmbers.end());

If you must insert items one-by-one from disparate sources, so you can't use the range-insertion, one option is to insert everything at the back, and then use std::rotate:
#include <algorithm>
v.reserve(v.size() + 6);
v.push_back(12);
v.push_back(foo());
// ...
std::rotate(v.begin() + 1, v.begin() + 4, v.end());

Something like this will insert 6 at the beginning of numbers:
numbers.insert(numbers.begin(), 6);
If you want to insert the number 6 after the number one:
numbers.insert(find(numbers.begin(), numbers.end(), 1), 6);
(Obviously, if you don't KNOW for sure that the number is in the list, you may want to check that before you insert!)

Related

Every sum possibilities of elements

From a given array (call it numbers[]), i want another array (results[]) which contains all sum possibilities between elements of the first array.
For example, if I have numbers[] = {1,3,5}, results[] will be {1,3,5,4,8,6,9,0}.
there are 2^n possibilities.
It doesn't matter if a number appears two times because results[] will be a set
I did it for sum of pairs or triplet, and it's very easy. But I don't understand how it works when we sum 0, 1, 2 or n numbers.
This is what I did for pairs :
std::unordered_set<int> pairPossibilities(std::vector<int> &numbers) {
std::unordered_set<int> results;
for(int i=0;i<numbers.size()-1;i++) {
for(int j=i+1;j<numbers.size();j++) {
results.insert(numbers.at(i)+numbers.at(j));
}
}
return results;
}
Also, assuming that the numbers[] is sorted, is there any possibility to sort results[] while we fill it ?
Thanks!
This can be done with Dynamic Programming (DP) in O(n*W) where W = sum{numbers}.
This is basically the same solution of Subset Sum Problem, exploiting the fact that the problem has optimal substructure.
DP[i, 0] = true
DP[-1, w] = false w != 0
DP[i, w] = DP[i-1, w] OR DP[i-1, w - numbers[i]]
Start by following the above solution to find DP[n, sum{numbers}].
As a result, you will get:
DP[n , w] = true if and only if w can be constructed from numbers
Following on from the Dynamic Programming answer, You could go with a recursive solution, and then use memoization to cache the results, top-down approach in contrast to Amit's bottom-up.
vector<int> subsetSum(vector<int>& nums)
{
vector<int> ans;
generateSubsetSum(ans,0,nums,0);
return ans;
}
void generateSubsetSum(vector<int>& ans, int sum, vector<int>& nums, int i)
{
if(i == nums.size() )
{
ans.push_back(sum);
return;
}
generateSubsetSum(ans,sum + nums[i],nums,i + 1);
generateSubsetSum(ans,sum,nums,i + 1);
}
Result is : {9 4 6 1 8 3 5 0} for the set {1,3,5}
This simply picks the first number at the first index i adds it to the sum and recurses. Once it returns, the second branch follows, sum, without the nums[i] added. To memoize this you would have a cache to store sum at i.
I would do something like this (seems easier) [I wanted to put this in comment but can't write the shifting and removing an elem at a time - you might need a linked list]
1 3 5
3 5
-----
4 8
1 3 5
5
-----
6
1 3 5
3 5
5
------
9
Add 0 to the list in the end.
Another way to solve this is create a subset arrays of vector of elements then sum up each array's vector's data.
e.g
1 3 5 = {1, 3} + {1,5} + {3,5} + {1,3,5} after removing sets of single element.
Keep in mind that it is always easier said than done. A single tiny mistake along the implemented algorithm would take a lot of time in debug to find it out. =]]
There has to be a binary chop version, as well. This one is a bit heavy-handed and relies on that set of answers you mention to filter repeated results:
Split the list into 2,
and generate the list of sums for each half
by recursion:
the minimum state is either
2 entries, with 1 result,
or 3 entries with 3 results
alternatively, take it down to 1 entry with 0 results, if you insist
Then combine the 2 halves:
All the returned entries from both halves are legitimate results
There are 4 additional result sets to add to the output result by combining:
The first half inputs vs the second half inputs
The first half outputs vs the second half inputs
The first half inputs vs the second half outputs
The first half outputs vs the second half outputs
Note that the outputs of the two halves may have some elements in common, but they should be treated separately for these combines.
The inputs can be scrubbed from the returned outputs of each recursion if the inputs are legitimate final results. If they are they can either be added back in at the top-level stage or returned by the bottom level stage and not considered again in the combining.
You could use a bitfield instead of a set to filter out the duplicates. There are reasonably efficient ways of stepping through a bitfield to find all the set bits. The max size of the bitfield is the sum of all the inputs.
There is no intelligence here, but lots of opportunity for parallel processing within the recursion and combine steps.

How can I insert multiple numbers to a particular element of a vector?

I am quite new to C++ and vector. I am calculating two things say 'i' and 'x' and I want to add 'x' that belongs to a particular vector element 'i'. I learned that if I have one 'x' value, I can simply do that by 'vec.at(i) = x'. But what if I want to add several 'x' values to a particular 'i' index of a vector?
Let's try to make it clear: Let's say I am searching for number '5' and '3' over a list of numbers from 1 to 10 (5 and 3 can occur multiple times in the list) and each time I am looking for number 5 or 3 that belong to index '2' of 'vec' I can do 'vec.at(2) = 5' or 'vec.at(2) = 3'. Then what if I have two '5' values and two '3' values so the sum of the index '2' of 'vec' will be '5+5+3+3' = 16?
P.S: using a counter and multiply concept will not solve my problem as the real problem is quite complicated. This query is just an example only. I want a solution within vector concept. I appreciate your help in advance.
If you know how many indices you want ahead of time, then try std::vector<std::vector<int>> (or instead of int use double or whatever).
For instance, if you want a collection of numbers corresponding to each number from 0 to 9, try
//This creates the vector of vectors,
//of length 10 (i.e. indices [0,9])
//with an empty vector for each element.
std::vector<std::vector<int>> vec(10, std::vector<int>());
To insert an element at a given index (assuming that there is something there, so in the above case there is only 'something there' for elements 0 through 9), try
vec.at(1).push_back(5);
vec.at(1).push_back(3);
And then to take the sum of the numbers in the vector at index 1:
int sum = 0;
for (int elem : vec.at(1)) { sum += elem; }
//sum should now be 8
If you want it to work for arbitrary indices, then it should be
std::map<int, std::vector<int>> map;
map[1].push_back(5); //creates an empty vector at index 1, then inserts
map[1].push_back(3); //uses the existing vector at index 1
int sum = 0;
for (int elem : map.at(1)) { sum += elem; }
Note that for std::vector and std::map, using [] do very different things. Most of the time you want at, which is about the same for both, but in this very specific case, [] for std::map is a good choice.
EDIT: To sum over every element in every vector in the map, you need an outer loop to go through the vectors in the map (paired with their index) and an inner loop like the one above. For example:
int sum = 0;
for (const std::pair<int, std::vector<int>>& index_vec : map) {
for (int elem : index_vec.second) { sum += elem; }
}

Add an element into the beginning of an vector, rest elements' position will add one

Assume I have an vector type of int(size 0). And I would like add elements into the beginning of the vector which would increase size by one.
Like I have elements in an vector are 1 2 3 4 5. Now I use that method add 6 into it. It will output in this order 6 1 2 3 4 5.
Is that possible?
http://www.cplusplus.com/reference/vector/vector/insert/
The following would be an example
int main ()
{
std::vector<int> myvector;
int myarray [] = { 1,2,3,4,5 };
myvector.insert (myvector.begin(), myarray, myarray+5);
// Insert another value
myvector.insert (myvector.begin(), 6);
return 0;
}
iterator insert (iterator position, const value_type& val);
Is probably what you are looking for, the iterator for inserting at the beginning is vector::begin

STL approaches for given loop

this loop works fine as expected. however is there any STL approach to mimic the exact functionality as the example below?
for (auto i = vec.size() - 1; i > 0; --i)
{
vec[i] = vec[i - 1];
}
Rather than an insertion or a rotate, all we're doing here is copying, so it seems like the thing to use is a copy. We could do the job with reverse_iterators:
std::copy(f.rbegin() + 1, f.rend(), f.rbegin());
...or with the algorithm really intended specifically for this sort of situation, std::copy_backward:
std::copy_backward(f.begin(), f.end()-1, f.end());
Either way, it's simple, straightforward, and about as efficient as possible (almost certainly more efficient than using insert/pop or rotate/assign).
std::rotate:
template< class ForwardIt >
ForwardIt rotate( ForwardIt first, ForwardIt n_first, ForwardIt last );
Used as (for a vector v)
// rotation left
std::rotate(v.begin(), v.begin() + 1, v.end());
// example:
// initial v: 1 2 3 4 5
// after rotate: : 2 3 4 5 1
// rotation right (as in your "script")
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
// example:
// initial v: 1 2 3 4 5
// after rotate: 5 1 2 3 4
//now if you do this,then it'll have the same effect as your code.
v[0] = v[1];
//before assignment: 5 1 2 3 4
//after assignment: 1 1 2 3 4
The difference w.r.t. your example is that, here, the first element will receive the previously last element (whereas in your code, the first element is untouched).
Performs a left rotation on a range of elements.
Specifically, std::rotate swaps the elements in the range [first,
last) in such a way that the element n_first becomes the first element
of the new range and n_first - 1 becomes the last element.
A precondition of this function is that [first, n_first) and [n_first,
last) are valid ranges.
http://en.cppreference.com/w/cpp/algorithm/rotate
The exact equivalent? Assuming the vector is not empty:
auto val = vec.front(); //Just in case the list is 1 element long.
vec.pop_back();
vec.insert(vec.begin(), val);
Your code effectively does this:
1 2 3 4 5 6
1 1 2 3 4 5
The first element is in two places, while the last element is lost. The above code does the same.

Insert a new value to element of array and move the rest of elements

I am making a program that it will be able to add any numbers on an array and then it will be able to modify them (insert,delete).What I want to know is how to create a new value in an array without modifying anything.Just create the value and push all the rest to the next one.Example: insert 1 8 //insert is just the command,1 is the place where you want to create the new value and 8 is the value itself so list[1] = 8 but I want the rest values that already exist to go 1 forward(if they are in the place I want to create the new value or higher than it(talking about place in the list))
Full example:
List:
5
6
7
8
9
Command: insert 3 10
New list:
5
6
7
10 //the one that changed,the rest from this point went 1 forward
8
9
What you want is to use a std::vector<int> something like this:
std::vector<int> v = {5, 6, 7, 8, 9};
v.insert(v.begin() + 1, 8); // v[1] now equals 8, everything after push up one
v.erase(v.begin() + 1); // v is now as it was before above insert
v.insert(v.begin() + 3, 10); // v[3] is now 10
One way would be to use std::vector and insert().
http://www.cplusplus.com/reference/vector/vector/
http://www.cplusplus.com/reference/vector/vector/insert/
Edit: unless you can't use STL containers and there's a requirement to use c-style arrays, in which case it won't be as straightforward, as you won't be able to directly grow them.
Let a be the array, position be the index in array where the value has to be inserted, and value be the value itself.
Then try:
int i;
for(i=CURRENT_SIZE_OF_ARRAY-1; i>=positon; --i)
{
a[i+1] = a[i];
}
a[i]=value;
This way, you shift the array values from the end in order to make space for the new element, and then finally insert that element in the desired location.