deleting multiple elements in an array - c++

i am trying to write a code that will delete all the elements if an array has same element at different index . it works fine for one element deletion or elements at odd index i.e 1,3,5 etc but it neglects one element if the consecutive index have same element.
i have just tried this to get my hands on arrays
for(int i=0;i<n;i++) //for deletion
{
if(arr[i]==_delete)
{
arr[i]=arr[i+1];
--n;
}
}

I suggest you use std::vector as a container for your objects.
std::vector<TYPE> vec ;
// initialise vector
You can use
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](const auto & item){return item == _delete;}), vec.end());
Alternatively, you can use std::list. Its list::erase has linear time complexity.

As an additional solution, if you want to deal with built-in C++ arrays, the standard std::remove algorithm can be rewritten like this:
void remove(int _delete) {
int j = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] != _delete) {
arr[j++] = arr[i];
}
}
// update the size!
n = j;
}
It's quite pretty:
We keep in the array the elements we only need, and override the ones in which we are not interested (they can be either equal or not to _delete and start at position j till the end)

Related

How can I find repeated words in a vector of strings in C++?

I have a std::vector<string> where each element is a word. I want to print the vector without repeated words!
I searched a lot on the web and I found lots of material, but I can't and I don't want to use hash maps, iterators and "advanced" (to me) stuff. I can only use plain string comparison == as I am still a beginner.
So, let my_vec a std::vector<std::string> initialized from std input. My idea was to read all the vector and erase any repeated word once I found it:
for(int i=0;i<my_vec.size();++i){
for (int j=i+1;j<my_vec.size();++j){
if(my_vec[i]==my_vec[j]){
my_vec.erase(my_vec.begin()+j); //remove the component from the vector
}
}
}
I tried to test for std::vector<std::string> my_vec{"hey","how","are","you","fine","and","you","fine"}
and indeed I found
hey how are you fine and
so it seems to be right, but for instance if I write the simple vector std::vector<std::string> my_vec{"hello","hello","hello","hello","hello"}
I obtain
hello hello
The problem is that at every call to erase the dimension gets smaller and so I lose information. How can I do that?
Minimalist approach to your existing code. The auto-increment of j is what is ultimately breaking your algorithm. Don't do that. Instead, only increment it when you do NOT remove an element.
I.e.
for (int i = 0; i < my_vec.size(); ++i) {
for (int j = i + 1; j < my_vec.size(); ) { // NOTE: no ++j
if (my_vec[i] == my_vec[j]) {
my_vec.erase(my_vec.begin() + j);
}
else ++j; // NOTE: moved to else-clause
}
}
That is literally it.
You can store the element element index to erase and then eliminate it at the end.
Or repeat the cycle until no erase are performed.
First code Example:
std::vector<int> index_to_erase();
for(int i=0;i<my_vec.size();++i){
for (int j=i+1;j<my_vec.size();++j){
if(my_vec[i]==my_vec[j]){
index_to_erase.push_back(j);
}
}
}
//starting the cycle from the last element to the vector of index, in this
//way the vector of element remains equal for the first n elements
for (int i = index_to_erase.size()-1; i >= 0; i--){
my_vec.erase(my_vec.begin()+index_to_erase[i]); //remove the component from the vector
}
Second code Example:
bool Erase = true;
while(Erase){
Erase = false;
for(int i=0;i<my_vec.size();++i){
for (int j=i+1;j<my_vec.size();++j){
if(my_vec[i]==my_vec[j]){
my_vec.erase(my_vec.begin()+j); //remove the component from the vector
Erase = true;
}
}
}
}
Why don't you use std::unique?
You can use it as easy as:
std::vector<std::string> v{ "hello", "hello", "hello", "hello", "hello" };
std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());
N.B. Elements need to be sorted because std::unique works only for consecutive duplicates.
In case you don't want to change the content of the std::vector, but only have stable output, I recommend other answers.
Erasing elements from a container inside a loop is a little tricky, because after erasing element at index i the next element (in the next iteration) is not at index i+1 but at index i.
Read about the erase-remove-idiom for the idomatic way to erase elements. However, if you just want to print on the screen there is a much simpler way to fix your code:
for(int i=0; i<my_vec.size(); ++i){
bool unique = true;
for (int j=0; j<i; ++j){
if(my_vec[i]==my_vec[j]) {
unique = false;
break;
}
if (unique) std::cout << my_vec[i];
}
}
Instead of checking for elements after the current one you should compare to elements before. Otherwise "bar x bar y bar" will result in "x x bar" when I suppose it should be "bar x y".
Last but not least, consider that using the traditional loops with indices is the complicated way, while using iterators or a range-based loop is much simpler. Don't be afraid of new stuff, on the long run it will be easier to use.
You can simply use the combination of sort and unique as follows.
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<std::string> vec{"hey","how","are","you","fine","and","you","fine"};
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end() ), vec.end());
for (int i = 0; i < vec.size(); i ++) {
std::cout << vec[i] << " ";
}
std::cout << "\n";
return 0;
}

Sort Array By Parity the result is not robust

I am a new programmer and I am trying to sort a vector of integers by their parities - put even numbers in front of odds. The order inside of the odd or even numbers themselves doesn't matter. For example, given an input [3,1,2,4], the output can be [2,4,3,1] or [4,2,1,3], etc. Below is my c++ code, sometimes I got luck that the vector gets sorted properly, sometimes it doesn't. I exported the odd and even vectors and they look correct, but when I tried to combine them together it is just messed up. Can someone please help me debug?
class Solution {
public:
vector<int> sortArrayByParity(vector<int>& A) {
unordered_multiset<int> even;
unordered_multiset<int> odd;
vector<int> result(A.size());
for(int C:A)
{
if(C%2 == 0)
even.insert(C);
else
odd.insert(C);
}
merge(even.begin(),even.end(),odd.begin(),odd.end(),result.begin());
return result;
}
};
If you just need even values before odds and not a complete sort I suggest you use std::partition. You give it two iterators and a predicate. The elements where the predicate returns true will appear before the others. It works in-place and should be very fast.
Something like this:
std::vector<int> sortArrayByParity(std::vector<int>& A)
{
std::partition(A.begin(), A.end(), [](int value) { return value % 2 == 0; });
return A;
}
Because the merge function assumes that the two ranges are sorted, which is used as in merge sort. Instead, you should just use the insert function of vector:
result.insert(result.end(), even.begin(), even.end());
result.insert(result.end(), odd.begin(), odd.end());
return result;
There is no need to create three separate vectors. As you have allocated enough space in the result vector, that vector can be used as the final vector also to store your sub vectors, storing the separated odd and even numbers.
The value of using a vector, which under the covers is an array, is to avoid inserts and moves. Arrays/Vectors are fast because they allow immediate access to memory as an offset from the beginning. Take advantage of this!
The code simply keeps an index to the next odd and even indices and then assigns the correct cell accordingly.
class Solution {
public:
// As this function does not access any members, it can be made static
static std::vector<int> sortArrayByParity(std::vector<int>& A) {
std::vector<int> result(A.size());
uint even_index = 0;
uint odd_index = A.size()-1;
for(int element: A)
{
if(element%2 == 0)
result[even_index++] = element;
else
result[odd_index--] = element;
}
return result;
}
};
Taking advantage of the fact that you don't care about the order among the even or odd numbers themselves, you could use a very simple algorithm to sort the array in-place:
// Assume helper function is_even() and is_odd() are defined.
void sortArrayByParity(std::vector<int>& A)
{
int i = 0; // scanning from beginning
int j = A.size()-1; // scanning from end
do {
while (i < j && is_even(A[i])) ++i; // A[i] is an even at the front
while (i < j && is_odd(A[j])) --j; // A[j] is an odd at the back
if (i >= j) break;
// Now A[i] must be an odd number in front of an even number A[j]
std::swap(A[i], A[j]);
++i;
--j;
} while (true);
}
Note that the function above returns void, since the vector is sorted in-place. If you do want to return a sorted copy of input vector, you'd need to define a new vector inside the function, and copy the elements right before every ++i and --j above (and of course do not use std::swap but copy the elements cross-way instead; also, pass A as const std::vector<int>& A).
// Assume helper function is_even() and is_odd() are defined.
std::vector<int> sortArrayByParity(const std::vector<int>& A)
{
std::vector<int> B(A.size());
int i = 0; // scanning from beginning
int j = A.size()-1; // scanning from end
do {
while (i < j && is_even(A[i])) {
B[i] = A[i];
++i;
}
while (i < j && is_odd(A[j])) {
B[j] = A[j];
--j;
}
if (i >= j) break;
// Now A[i] must be an odd number in front of an even number A[j]
B[i] = A[j];
B[j] = A[i];
++i;
--j;
} while (true);
return B;
}
In both cases (in-place or out-of-place) above, the function has complexity O(N), N being number of elements in A, much better than the general O(N log N) for sorting N elements. This is because the problem doesn't actually sort much -- it only separates even from odd. There's therefore no need to invoke a full-fledged sorting algorithm.

putting elements from vector into queue then clearing vector

I'm looking for the simplest way(algorithm?) to push an entire vector onto a queue and then delete the vector. I think there are a few ways to do this but I'm not sure which is best, or if all of them are correct. Option 1 is to use vector.pop_back(), but I'd have to go backwards through the for loop in this case, which isn't a problem since the order the objects go into the queue from the vector do not matter
for(unsigned i = vector.size() - 1; i >= 0; i--){
queue.push(vector[i]);
vector.pop_back();
}
Option 2 is to use vector.erase(). Also is it okay to do i < vector.size()? Because when I looked online for iterating through vectors I found a lot of i != vector.size() instead
for(unsigned i = 0; i < vector.size(); i++){
queue.push(vector[i]);
vector.erase[i];
}
My issue here is that if I erase vector[i], does vector [i+1] now become vector[i]? Or does vector[i] become a Null value?
My 3rd option would be to just erase it all at the end
for(unsigned i = 0; i < vector.size(); i++){
queue.push(vector[i]);
}
vector.erase(vector.begin(), vector.end());
Just for clarity, I don't want to get rid of the vector variable itself, just empty it after putting it into the queue, because it will eventually store a bunch of new things to dump into a queue again and again.
If you don't mind the objects being present in both the queue and the vector for a while, just do the simplest thing: your 3rd option, just with a clear() instead to be explicit what you're doing:
for(size_t i = 0; i < vector.size(); i++){
queue.push(vector[i]);
}
vector.clear();
Of course, in C++11, you could use a range-based for loop, and even move the items out of the vector to avoid needless copies:
for (auto &elem : vector) {
queue.push(std::move(elem));
}
vector.clear();
A)
for(unsigned i = vector.size() - 1; i >= 0; i--){
queue.push(vector[i]);
vector.pop_back();
}
This should be a bit less efficient then C)
B)
for(unsigned i = 0; i < vector.size(); i++){
queue.push(vector[i]);
vector.erase[i];
}
"My issue here is that if I erase vector[i], does vector [i+1] now become vector[i]? Or does vector[i] become a Null value?"
Erase[i] doesn't work at all. You could ruse erase(vector.begin()) pulling elements from the vectors head one by one, but its not very efficient and the whole loop should end up with O(N^2/2) since your deleting from the vectors head.
C)
for(unsigned i = 0; i < vector.size(); i++){
queue.push(vector[i]);
}
vector.clear();
Should be the most efficient way to go.
Note
The result of A and B since in A you're pulling elements from the tail while taking them from the head in C
Unless the element-type is large, you can't do much (except move which #Angew suggested). If element size is small, there is no benefit of move either - the memory layout of both vector and queue are different. If element-type is large, you may consider using pointers (in a list or vector) of elements.
If you were to use a deque instead of queue then you could do an insert and insert all the elements at once.
Something like
template <class T, template <typename, typename> class Container>
class BlockQueue : public Container<T, std::allocator<T>>
{
public:
BlockQueue() : Container<T, std::allocator<T>>()
{
}
void push( T val )
{
this->push_back( val );
}
void push( const std::vector<T>& newData )
{
this->insert( this->end(), newData.begin(), newData.end() );
}
};

Array sorting backwards?

Okay so I have this function that takes an array and sorts it by using swap sort(?) however when I enter the numbers it sorts it from largest to smallest instead of smallest to largest.
I went through and did this to see what happens each step of the way however it all seems correct to me.
iterator = &first element
temp = smallest number
tempstore = &smallest number
val tempstore = val first element
val first element = val temp
If i change it so that
if(array[i] < *iterator)
becomes:
if(array[i] > *iterator)
it works perfectly but I don't understand this as now it is testing to see if the number is larger and I want smaller.
I know I should probably be using a vector but I am still a newbie and I am yet to learn them. Thanks for any help.
int *sort(int *array, int size)
{
int temp, *iterator, *tempStore;
for(int j = 0; j < size; j++)
{
iterator = &array[j];
for(int i = 0; i < size; i++)
{
if(array[i] < *iterator)
{
temp = array[i];
tempStore = &array[i];
*tempStore = *iterator;
*iterator = temp;
}
}
}
return array;
}
Your algorithm compares the first element of the array with all the subsequent, so when you use:
if(array[i] > *iterator)
you swap the first element with the ith element every time the ith element is greater than the first. So at the end of the first pass you have the greatest element in the first position. if you use the < operator, you get the smallest in front.
Then the second pass should compare the second element of the array with all the subsequent and so on, that's why i needs to start iterating from j + 1.
As you saw it is not straightforward to read and understand the code, moreover the algorithm itself is very poor (it looks like a selection sort with some extra swaps). You do not necessarily need to use a std::vector but you really should learn the standard library.
This is the C++11 way to do it:
#include <algorithm> //for std::sort
#include <iterator> //for std::begin/end
#include <functional> //for std::greater
int v[1000];
... fill v somehow ...
std::sort(std::begin(v), std::end(v), std::greater<int>());
Compact, clear and extremely fast.

How to find indexes of 5 the biggest elements in vector?

How to find indexes of 5 the biggest elements in vector ?
For example std::vector<int> how to find indexes of 5 biggest values but not to change original vector ?
std::partial_sort( v.begin(), v.begin()+5, v.end() ) sorts a vector in a way, that the 5 smallest values are sorted and at the beginning of v. The rest is left unsorted.
Since you want the indices and keep the original:
Fill a new vector with numbers from 0..n-1 and supply a comparison function that does v[a] > v[b] instead of a > b:
struct Comp{
Comp( const vector<int>& v ) : _v(v) {}
bool operator ()(int a, int b) { return _v[a] > _v[b]; }
const vector<int>& _v;
}
vector<int> vx;
vx.resize(v.size());
for( int i= 0; i<v.size(); ++i ) vx[i]= i;
partial_sort( vx.begin(), vx.begin()+5, vx.end(), Comp(v) );
vx[0..4] contains the indices.
1 solution:
The solution is O(n), where n is the number of elements in the vector being examined.
create a dequeue of vector iterators of length 5, initialized with NULL
read the elements of the vector under examination and push_back the index {the idea is to push the new index in the front or back depending upon whether the new element data read is smaller than rear index's data or greater than the front index's data, if the data already in the dequeue is NULL, then whether you push_front or push_back, it doesn't matter}. This would maintain the dequeue in the sorted from from front to back.
If the new data being read is greater than the front data, then remove the rear and push the current data's iterator in front; else do nothing
At the end of the iteration the dequeue will have top five element's iterators.
You can make a copy from the original vector, and partially sort it with a dedicated algorithm from the STL nth_element :
bool cmp (int i,int j) { return (i<j); }
int main () {
vector<int> myvector;
vector<int>::iterator it;
// set some values:
for (int i=1; i<10; i++) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
random_shuffle (myvector.begin(), myvector.end());
// using default comparison (operator <):
std::vector<int> copy_of_orig = myvector;
nth_element (copy_of_orig.begin(), copy_of_orig.begin()+5, copy_of_orig.end(), cmp);
// Display the first five biggest elts.
for (int i = 0; i < 5; ++i)
std::cout << copy_of_orig[i] << std::endl;
}
There might be a more elegant way, but I'm to tired to find it right now. You could do something like this (untested, so no guarantees it works out of the box, particulary in corner cases, but it should):
std::array<int, 5> indices = {-1,-1,-1,-1,-1};//-1 used as invalid index for cases where myVec.size()<5
for(int i = 0; i < myVec.size(); ++i)
{
for(int j = 0; j < 5; ++j)
if((indices[j] == - 1) || (myVec[i] > myVec[indices[j]]))
{
std::copy_backward(indices.begin() + j, indices.end() - 1, indices.end());
indices[j] = i;
break;
}
}
It maintains a list of the 5 biggest elements. For each element of the vector it will start with the biggest element, test if the new one is bigger, if yes shift the indices down and insert as the first, otherwise test for the second biggest and so on. Doesn't modify the vector and runs in O(n) with pretty low overhead.
In case you can't use C++11, you can always use an std::vector (or int[5] if you really want to) instead of std::array.
You will need to do something like this:
int largestNumbers [5]{0, 0, 0, 0, 0};
for each( const int i in data ){
{
for (int index = 0; index < 5; index++){
if (i > largestNumber[index]){
largestNumber[index] = i;
}
}
}