Vector split/shift elements - c++

I've std::vector<type> myVector
lets say content is:
el1, el2, el3, splitElement, el4,el5
I'm splitting splitElement into split1 and split2
I want to have vector:
split2, el4, el5, el1, el2, el3, split1
Split2 should be begining, split1 end. Other elements order should be like in example. Let's treat vector as chain. I want to insert two elements and shift chain to make split2 first element.
What is the elegant and effective way doing it using stl.
My fast code for now (it's very ugly solution):
std::vector<type> before;
std::vector<type> after;
bool afterBool = false;
for(std::vector<type>::iterator it = myVector.begin(); it != myVector.end(); it++)
{
if(*it == splitElement)
{
afterBool = true;
before.push_back(split1);
after.push_back(split2);
}
else if(afterBool)
after.push_back(*it);
else
before.push_back(*it);
}
myVector.clear();
for(std::vector<type>::iterator it = after.begin(); it != after.end(); it++)
myVector.push_back(*it);
for(std::vector<type>::iterator it = before.begin(); it != before.end(); it++)
myVector.push_back(*it);
I've added it only cause I don't wanted to leave topic without any code.
How to do it in nice way?

Example:
std::vector<int> myvector = {1, 2, 3, 0, 4, 5};
int splitElement = 0;
int split1 = -1;
int split2 = -2;
First you find your splitElement:
auto it = std::find(myvector.begin(), myvector.end(), splitElement);
Then you rotate the vector at the point you found splitElement, using std::rotate algorithm:
std::rotate(myvector.begin(), it, myvector.end());
// this yields { 0, 4, 5, 1, 2, 3 }
And finally just assign split2 to the beggining and push split1 to the back:
myvector[0] = split2;
myvector.push_back(split1);
The vector now looks like this: {-2, 4, 5, 1, 2, 3, -1}.

It sounds like you want to partition your vector. So you can use std::partition
To take your example with integers and -1 as the split element.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Splitter
{
int split;
Splitter(int sp):split(sp){}
bool operator()(int i)
{
return split < i;
}
};
int main () {
vector<int> myvector;
vector<int>::iterator it, bound;
// set some values:
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
bound = partition (myvector.begin(), myvector.end(), Splitter(5));
myvector.insert(bound, -1);
cout << "odd members:";
for (it=myvector.begin(); it!=myvector.end(); ++it)
cout << " " << *it;
cout << endl;
return 0;
}

Since you havent mentioned about the sorting requirement and < operation on the type.
i guess you just want to split the element and make the first split as the last element in a vector and second split as the first element of the vector
I guess the better way to do this is to use a Data structure (Linked list)
store the elements of the vector in LL
traverse the list till the split element
make the second element as head and first element as the tail of LL
the original tail should be pointing its next to original tal.
aftere these above operation are done.just traverse the ll and store back in a vector.

Related

how to loop a increasing container in c++? [duplicate]

This question already has answers here:
Appending to a vector while iterating over it?
(8 answers)
Closed 15 days ago.
I want to loop a increasing container, for example, if the container is std::vector. i need to push_back when looping the vector elements.
std::vector<int> v = {1, 3,5, 7,9};
for (auto i : v) { // v is std::vector
if (i % 2 == 1) v.push_back(i + 1); // just a demo, the push_back will happen in some condition, won't be a endless loop
printf("%d ", i);
} // the expected result is : 1, 3, 5, 7, 9, 2, 4, 6, 8, 10
I know vector is not the correct container, is there any good tools can handle this?
The problem is, as 463035818_is_not_a_number said in the comments, push_back() can (potentially) invalidates iterators. (for example, it can make std::vector to re-reallocate).
A much simpler solution is to use a for loop instead:
int main()
{
std::vector<int> v = {1, 3,5, 7,9};
for (int i = 0; i < v.size(); ++i)
{
if (v[i] % 2 == 1)
{
v.push_back(v[i] + 1);
}
std::cout << v[i] << ' ';
}
}
Link.
You can't use iterators or a range based for loop because of reallocation. But there's nothing wrong with the old-school approach of using an index. That's immune to reallocation
std::vector<int> v = {1, 3, 5, 7, 9};
for (size_t i = 0; i < v.size(); ++i) {
if (v[i] % 2 == 1)
v.push_back(v[i] + 1);
printf("%d ", v[i]);
}
push_back invalidates iterators when the vector has to reallocate. You can resevere enough space and use an iterator based loop:
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {1, 3,5, 7,9};
v.reserve(v.size()*2);
auto begin = v.begin();
auto end = v.end();
for (; begin != end; ++begin) {
if (*begin % 2 ==1) v.push_back(*begin + 1);
}
for (const auto& e : v) std::cout << e << " ";
}
This assumes that you only need to iterate the elements that were already in the vector before the loop. (Your code assumes that the loop iterates also the newly added ones, but the condition is such that this is not necessary. You need a second loop for printing then.)
Alternatively you could use an index based loop:
auto s = v.size();
for (size_t i=0; i < s; ++i) {
// ....

C++: Every time, the function is returning empty vector. Why?

I have been trying to solve this problem:
Given an array of integers, return indices of the two numbers such
that they add up to a specific target.
You may assume that each input would have exactly one solution,
and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
I have been trying to solve this using map and my attempted solution is below:
#include <iostream>
#include <map>
#include <vector>
using namespace std;
vector<int> twoSum(vector<int>& nums, int target) {
std::map<int, int> indices;
for (int i = 0; i < nums.size(); ++i) {
auto it = indices.find(target - nums[i]);
if (it != indices.end())
return {it->first, i};
indices[i] = nums[i];
}
return {};
}
int main() {
std::vector<int> nums = {2, 7, 11, 15};
int target = 9;
std::vector<int> ans = twoSum(nums, target);
for(const auto &elem : ans) {
std::cout << elem << " ";
}
std::cout << "\n";
return 0;
}
To avoid two for loops, I'm trying to find target - num2 because num1 + num2 = target.
So, the logic is to
create a map from the input vector nums
use map.find(target - num[i])
return the first value of iterator pointing to target-nums[i], i.e., the key for the value = target-nums[i], in the map and i.
Therefore, for the above code, the function should return {0, 1}
However, every time, I get an empty vector. Could anyone please tell me whether my logic is wrong or I'm manipulating the map or vector wrongly?
You are very close to solving the problem but your code has a small yet critical issue.
You add elements to your map as (key=index, value=number)
indices[i] = nums[i];
... Essentially, you just recreated the array in a different format, so if you think about it, for every i, nums[i] == indices[i]. This approach really doesn't get you any further in solving your problem.
Instead, you should try mapping (key=number, value=index)
indices[nums[i]] = i;
This way, when you search the map for a previously-encountered number as you already are
auto it = indices.find(target - nums[i]);
... You end up searching for the number itself instead of an index!
Note that you will also need to change the return to use the index instead of the value, as the format of your map is now different
auto it = indices.find(target - nums[i]);
if (it != indices.end())
return {it->second, i};
try doing: indices[num[i]] = 1.
You are using the index as the key of the map, but you should really be using the values.
Don't use a map at all.
std::vector<int> twoSum(const std::vector<int> & nums, int target) {
for (int it1 = nums.begin(); it1 != nums.end(); ++it1) {
auto it2 = std::find(std::next(it1), nums.end(), target - *it1);
if (it2 != nums.end())
return {std::distance(nums.begin(), it1), std::distance(nums.begin(), it2)};
}
// You can assume this is never reached, throwing is noisier than returning empty
throw std::runtime_error("invalid arguments to twoSum");
}

How to consider only first two elements from *pointer

From the below code you can see that the vector array has the same number twice or more than. What I want to do is to find the first two same number's position from the pointer *ptr
#include<iostream>
#include<iterator> // for iterators
#include<vector> // for vectors
using namespace std;
int main()
{
vector<int> ar = { 1,8,2, 2, 2, 5,7,7,7,7,8 };
// Declaring iterator to a vector
vector<int>::iterator ptr;
// Displaying vector elements using begin() and end()
cout << "The vector elements are : ";
for (ptr = ar.begin(); ptr < ar.end(); ptr++)
cout << *ptr << " ";
return 0;
}
Let's assume I want to print out the first two position and elements of 7 by dereferencing the pointer *ptr. Should I use an if a condition like
int *array = ptr.data();
for( int i =0; i < ar.size(); i++) {
if( array[i] - array[i+1]+ ==0)
cout<<array[i]<<endl;
}
But how would I guarantee that it is not looking for the only first two same elements from *ptr?
UPDATE
Clearing the question:
The reason I always want to know the first and second position of the same element from the dereferencing the pointer is that later I will do some study, and in that study, I will be given some time associated with the first and second position of the same number. The problem, I wanted to ignore the same elements which are still repetitive after the second time is because I want to ignore these element positions in my calculations.
For example, if you print out the code you would find the element: **The vector elements are 1 8 2 2 2 5 7 7 7 7 8 **. In this case, the first two positions of the element 2, is [2], and [3], therefore I would like to ignore the position [4]. Another thing to mention, that I don't care if the value or consequent or not[I mean for example 828, or 888, I would consider both]. For example, the number 8 is in location array[1], and in the [10]. I would also consider this.
Create a map where each value is stored as key, mapped to a list of indices:
std::unordered_map<int, std::vector<size_t>> indexMap;
Loop over your initial values and fill the map:
for (size_t index = 0; index < ar.size(); index++)
{
indexMap[ar[index]].push_back(index);
}
Now you can loop over your map and work with every value that has 2 or more indices and only use the first 2 indices for whatever you want to do:
for (auto const& [value, indices] : indexMap)
{
if (indices.size() < 2)
continue;
size_t firstIndex = indices[0];
size_t secondIndex = indices[1];
// do whatever
}
(If you don't use C++17 or up, use for (auto const& pair : indexMap), where pair.first is value and pair.second is indices.)
You could use map or unordered_map to register indexes of each value.
Here's a simple demo of the concept:
#include<iostream>
#include<vector>
#include<map>
using namespace std;
int main() {
vector<int> ar{ 1, 8, 2, 2, 2, 5, 7, 7, 7, 7, 8 };
map<int, vector<size_t> > occurrences{ };
for (size_t i = 0; i < ar.size(); ++i) {
occurrences[ar[i]].push_back(i);
}
for (const auto& occurrence:occurrences) {
cout << occurrence.first << ": ";
for (auto index: occurrence.second) {
cout << index << " ";
}
cout << endl;
}
return 0;
}
Output:
1: 0
2: 2 3 4
5: 5
7: 6 7 8 9
8: 1 10

How to find next element in a vector C++

I am using a vector in a C++ program and I would like to find the next element inside the vector when looping through it, similar to how it would work with a linked list creating a next node. I am planning to use this loop to check the current element in a vector against the next element to see if they are the same.
for (auto i = v.begin(); i < v.end()-1; ++i) {
if (i[0] == i[1]) {
// do stuff
}
}
You can just use this loop:
for (size_t i = 0; i < v.size()-1; ++i) {
if (v[i] == v[i+1] { // if current element equals next element
... // do something
}
}
Simple
You can use std::next.
// Example copied from page linked to.
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v{ 3, 1, 4 };
auto it = v.begin();
auto nx = std::next(it, 2);
std::cout << *it << ' ' << *nx << '\n';
}
// Output:
// 3 4
In case you use the vector as a circular list (that is, you consider the first element as the "next" of the last element), you can use the modulo operator against the length of the vector.
For example:
int getNext(std::vector<int> vect, size_t i) {
return vect[ (i+1) % v.size() ];
}
This solution is useful if you need to select the next element in a "round robin" way, especially out of a loop.

Finding consecutive elements in a vector

I am working on a problem where I have to create subvectors from a bigger vector. If the elements in the vector are consecutive I have to create a vector of those elements. If there are elements which are not consecutive then a vector of that single elements is created. My logic is as below
vector<int> vect;
for (int nCount=0; nCount < 3; nCount++)
vect.push_back(nCount);
vect.push_back(5);
vect.push_back(8);
vector<int>::iterator itEnd;
itEnd = std::adjacent_find (vect.begin(), vect.end(), NotConsecutive());
The functor NotConsecutiveis as below
return (int first != int second-1);
So I am expecting the std::adjacent_find will give me back the iterators such that I can create vector one{0,1,2,3}, vector two{5} and vector{8}. But I am not sure if there is any simpler way?
Edit:I forgot to mention that I have std::adjacent_find in a loop as
while(itBegin != vect.end())
{
itEnd = std::adjacent_find (vect.begin(), vect.end(), NotConsecutive());
vector<int> groupe;
if( std::distance(itBegin, itEnd) < 1)
{
groupe.assign(itBegin, itBegin+1);
}
else
{
groupe.assign(itBegin, itEnd);
}
if(boost::next(itEnd) != vect.end())
{
itBegin = ++itEnd;
}
else
{
vector<int> last_element.push_back(itEnd);
}
}
Does it make any sense?
I think this is what is being requested. It does not use adjacent_find() but manually iterates through the vector populating a vector<vector<int>> containing the extracted sub-vectors. It is pretty simple, IMO.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vect { 0, 1, 2, 3, 5, 8 };
// List of subvectors extracted from 'vect'.
// Initially populated with a single vector containing
// the first element from 'vect'.
//
std::vector<std::vector<int>> sub_vectors(1, std::vector<int>(1, vect[0]));
// Iterate over the elements of 'vect',
// skipping the first as it has already been processed.
//
std::for_each(vect.begin() + 1,
vect.end(),
[&](int i)
{
// It the current int is one more than previous
// append to current sub vector.
if (sub_vectors.back().back() == i - 1)
{
sub_vectors.back().push_back(i);
}
// Otherwise, create a new subvector contain
// a single element.
else
{
sub_vectors.push_back(std::vector<int>(1, i));
}
});
for (auto const& v: sub_vectors)
{
for (auto i: v) std::cout << i << ", ";
std::cout << std::endl;
}
}
Output:
0, 1, 2, 3,
5,
8,
See demo at http://ideone.com/ZM9ssk.
Due to the limitations of std::adjacent_find you can't use it quite the way you want to. However it can still be useful.
What you can do is to iterate over the collection, and use std::adjacent_find in a loop, with the last returned iterator (or your outer loop iterator for the first call) until it returns end. Then you will have a complete set of consecutive elements. Then continue the outer loop from where the last call to std::adjacent_find returned a non-end iterator.
Honestly, I don't find any clear disadvantage of using a simple hand-crafted loop instead of standard functions:
void split(const std::vector<int> &origin, vector<vector<int> > &result)
{
result.clear();
if(origin.empty()) return;
result.resize(1);
result[0].push_back(origin[0]);
for(size_t i = 1; i < origin.size(); ++i)
{
if(origin[i] != origin[i-1] + 1) result.push_back(vector<int>());
result.back().push_back(origin[i]);
}
}