How to remove odd numbers from array - c++

It looks like every time there are consecutive odd numbers three lines in a
row in array. One in the middle that does not get removed.
I see why this is happening but I'm not too sure how I can fix it.
This is for C++.
#include <iostream>
using namespace std;
void removeodd(int arr[],int& number)//{1,2,3,6,7,9,5,8};
{int count=0;
for(int i=0; i<number; i++)
{
if(arr[i]%2!=0)
{
int j=i+1;
for(int k=i;k<number; k++)
{
arr[k]=arr[j];
j++;
}
count++;
}
}
number=number-count;
for(int i=0; i<number; i++){
cout<<arr[i]<<" ";
}
}
int main(){
int size=8;
int ary[8]={1,2,3,6,7,9,5,8};
removeodd(ary, size);
return 0;
}
output of the code above is 2 6 9 8

The problem is that you're always advancing your index, even if you remove an odd number. So if there are two odd numbers, you remove the first one and move the index past the second one. To fix this, decrease the index again when you remove and odd number. So after this:
count++;
Also put this:
i--;
And the output you get is:
2 6 8

in your for loop..
assume value when the value 1 is deleted.
and in array ary is { 2,3,6,7,9,5,8 }
but i value is 1, so you did't check value 2 is odd number.
so fix the loop check all values.

You are making things difficult on yourself using an array of fundamental types (e.g. int) instead of a C++ container which contains member functions that allow you to .erase() any element in your array. A choice of a vector<int> will allow you to remove odd values in a trivial manner.
For example,
#include <vector>
...
std::vector<int> arr {1,2,9,6,7,3,5,8};
will create your array as a vector<int>. As a vector container you can simply iterate over each element in your vector from arr.begin() to arr.end() using a simple iterator. The only caveat, is you must revalidate the iterator after each erasure as iterators are invalidated on container changes. To revalidate your iterator, you simply assign the result of the .erase() operation, e.g.
for (auto it = arr.begin(); it != arr.end();) { /* iterate vector */
if (*it & 1u) /* if value is odd */
it = arr.erase(it); /* erase it saving/revalidating iter */
else /* otherwise */
it++; /* simply advance iter */
}
Putting it together in a short example that outputs the original arr, removes odd numbers, and then outputs arr again with the odd numbers removed, you could do:
#include <iostream>
#include <vector>
int main (void) {
std::vector<int> arr {1,2,9,6,7,3,5,8};
for (auto& v: arr) /* output original vector contents */
std::cout << " " << v;
std::cout << '\n';
for (auto it = arr.begin(); it != arr.end();) { /* iterate vector */
if (*it & 1u) /* if value is odd */
it = arr.erase(it); /* erase it saving/revalidating iter */
else /* otherwise */
it++; /* simply advance iter */
}
/* output remaining even values */
for (auto& v: arr)
std::cout << " " << v;
std::cout << '\n';
}
Example Use/Output
$ ./bin/vect_remove_odd
1 2 9 6 7 3 5 8
2 6 8
Look things over and let me know if you have further questions.

Related

Duplicates in Array

Given an integer array nums sorted in non-decreasing order, remove some duplicates in-place such that each unique element appears at most twice. The relative order of the elements should be kept the same.
Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.
Return k after placing the final result in the first k slots of nums.
What is wrong with my code ??
map<int,int> m;
for(int i = 0 ; i < nums.size() ; i++){
m[nums[i]]++;
if(m[nums[i]] > 2)nums.erase(nums.begin() + i);
}
return nums.size();
From the given text, we can derive the following requirements
Given an integer array nums
sorted in non-decreasing order,
remove some duplicates in-place such that each unique element appears at most twice.
The relative order of the elements should be kept the same.
Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums.
More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result.
It does not matter what you leave beyond the first k elements
Return k after placing the final result in the first k slots of nums.
So, after elicitating the requirements, we know that we have a fixed size array, presumably (because of the simplicity of the task) a C-Style array or a C++ std::array. Because of the shown source code, we assume a std::array.
It will be sorted in increasing order. Their shall be an in-place removal of elements. So, no additional variables. The rest of the requirements already shows the solution.
--> If we find duplicates (more than 2) we will shift the rest of the values one to the left and overwrite one of the duplicates. Then the logical number of elements in the array will be one less. So, the loop must run one step less.
This ends up in a rather simple program:
#include <iostream>
#include <array>
// Array with some test values
constexpr int ArraySize = 25;
std::array<int, ArraySize> nums{ 1,2,2,2,3,3,3,4,4,4,4,4,6,5,5,5,5,5,6,6,6,6,6,6,9,9 };
int main() {
// Currentlogical end of the data in the array. In the beginning, last value in the array
size_t endIndex = nums.size();
// Check allelments from left to tright
for (size_t index = 0; index < endIndex;) {
// Check, if 3 elements are same
if ((index < (endIndex -2)) and nums[index] == nums[index + 1] and nums[index + 1] == nums[index + 2]) {
// Yes, found 3 same elements. We willdelete one, so the endIndex needs to be decremented
--endIndex;
// Now hsift all array elements one to the left
for (size_t shiftIndex = index + 2; shiftIndex < endIndex; ++shiftIndex)
nums[shiftIndex] = nums[shiftIndex + 1];
}
else ++index;
}
// SHow result
std::cout << endIndex << '\n';
}
I can offer the solution of your problem.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
void showContentSet(set<int>& input)
{
for(auto iterator=input.begin(); iterator!=input.end(); ++iterator)
{
cout<<*iterator<<", ";
}
return;
}
void showContentVector(vector<int>& input)
{
for(int i=0; i<input.size(); ++i)
{
cout<<input[i]<<", ";
}
return;
}
void solve()
{
vector<int> numbers={1, 2, 1, 3, 4, 5, 7, 5, 8, 5, 9, 5};
set<int> indicesToDelete;
for(int i=0; i<numbers.size(); ++i)
{
int count=0;
for(int j=0; j<numbers.size(); ++j)
{
if(numbers[i]==numbers[j])
{
++count;
if(count>2)
{
indicesToDelete.insert(j);
}
}
}
}
cout<<"indicesToDelete <- ";
showContentSet(indicesToDelete);
int newOrder=0;
cout<<endl<<"Before, numbers <- ";
showContentVector(numbers);
for(auto iterator=indicesToDelete.begin(); iterator!=indicesToDelete.end(); ++iterator)
{
numbers.erase(numbers.begin()+(*iterator-newOrder));
++newOrder;
}
cout<<endl<<"After, numbers <- ";
showContentVector(numbers);
cout<<endl;
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
indicesToDelete <- 9, 11,
Before, numbers <- 1, 2, 1, 3, 4, 5, 7, 5, 8, 5, 9, 5,
After, numbers <- 1, 2, 1, 3, 4, 5, 7, 5, 8, 9,
I suggest using a frequency array.
frequency array works, That you count how many duplicates of each number while inputting, It's stored usually in an array called freq, Also can be stored in a map<int, int> or unordered_map<int, int>.
And because of input is in non-decreasing order, outputting this solution will be easy.
Note: this solution won't work if input numbers is bigger than 10^5
Solution:
#include <iostream>
const int N = 1e5 + 1; // Maximum size of input array
int n;
int nums[N], freq[N];
int main()
{
// Input
std::cin >> n;
for (int i = 0; i < n; i++)
{
std::cin >> nums[i];
freq[nums[i]]++;
}
// Outputting numbers, Using frequency array of it
for (int i = 0; i < N; i++)
{
if (freq[i] >= 1)
std::cout << i << ' ';
if (freq[i] >= 2)
std::cout << i << ' ';
}
return 0;
}
This is basically a conditional copy operation. Copy the entire range, but skip elements that have been copied twice already.
The following code makes exactly one pass over the entire range. More importantly it avoids erase operations, which will repeatedly shift all elements to the left.
vector<int> nums; // must be sorted already
if (nums.size()<=1)
return; // already done
// basically you copy all elements inside the vector
// but copy them only if the requirement has been met.
// `in` is the source iterator. It increments every time.
// `out` is the destination iterator. It increments only
// after a copy.
auto in=nums.begin();
auto out=nums.begin();
// current is the current 'int' value
int current=*in;
// `count` counts the repeat count of the current value
int count=0;
while (in!=nums.end()) {
if (*in==current) {
// The current value repeats itself, so increment
// the count value
++count;
} else {
// No, this is a new value.
// initialise current and count
current=*in;
count=1;
}
if (count<=2) {
// only if at most two elements of the same value
// copy the current value to `out`
*out=current;
++out;
}
// try next element
++in;
}
// out points to the last valid element + 1

Count Number of Digits in an array (c++)

let's say I have an array
arr[5]={5,2,3,2,5} and i wrote following program for it
#include <iostream>
using namespace std;
int main()
{
int n;
cout<<"Enter Length of Elements= ";
cin>>n;
int arr[50];
for(int i=0;i<n;i++)
{
cout<<"Enter Number=";
cin>>arr[i];
}
for(int i=0;i<n;i++)
{
int countNum=1;
for(int j=i+1;j<n;j++)
{
if(arr[i]==arr[j])
{
if(i>0)
{
int countNum2=0;
for(int k=0;k>i;k++)
{
//bool repeat=false;
if(arr[i]==arr[k])
{
//repeat=false;
}
else
{
countNum2++;
}
}
if(countNum2==i)
{
countNum++;
}
}
else
{
countNum++;
}
}
else
{
for(int k=0;k<i;k++)
{
if(arr[k]==arr[i])
{
}
else
{
countNum=1;
}
}
}
}
cout<<arr[i]<<" has appeared "<<countNum<< "Times"<<endl;
}
return 0;
}
but why I am getting
5 has appeared 2 Times
2 has appeared 1 Time
3 has appeared 1 Time
2 has appeared 1 Time
5 has appeared 1 Time
instead of
5 has appeared 2 Times
2 has appeared 2 Times
3 has appeared 1 Times
so how to fix my program
help!
That's what you exactly need (amount of each number in array):
// we'll store amounts of numbers like key-value pairs.
// std::map does exactly what we need. As a key we will
// store a number and as a key - corresponding counter
std::map<int, size_t> digit_count;
// it is simpler for explanation to have our
// array on stack, because it helps us not to
// think about some language-specific things
// like memory management and focus on the algorithm
const int arr[] = { 5, 2, 3, 2, 5 };
// iterate over each element in array
for(const auto elem : arr)
{
// operator[] of std::map creates default-initialized
// element at the first access. For size_t it is 0.
// So we can just add 1 at each appearance of the number
// in array to its counter.
digit_count[elem] += 1;
}
// Now just iterate over all elements in our container and
// print result. std::map's iterator is a pair, which first element
// is a key (our number in array) and second element is a value
// (corresponding counter)
for(const auto& elem : digit_count) {
std::cout << elem.first << " appeared " << elem.second << " times\n";
}
https://godbolt.org/z/_WTvAm
Well, let's write some basic code, but firstly let's consider an algorithm (it is not the most efficient one, but more understandable):
The most understandable way is to iterate over each number in array and increment some corresponding counter by one. Let it be a pair with the first element to be our number and the second to be a counter:
struct pair {
int number;
int counter;
};
Other part of algorithm will be explained in code below
// Say that we know an array length and its elements
size_t length = // user-defined, typed by user, etc.
int* arr = new int[length];
// input elements
// There will be no more, than length different numbers
pair* counts = new pair[length];
// Initialize counters
// Each counte will be initialized to zero explicitly (but it is not obligatory,
// because in struct each field is initialized by it's default
// value implicitly)
for(size_t i = 0; i < length; i++) {
counts[i].counter = 0;
}
// Iterate over each element in array: arr[i]
for(size_t i = 0; i < length; i++)
{
// Now we need to find corresponding counter in our counters.
size_t index_of_counter = 0;
// Corresponding counter is the first counter with 0 value (in case when
// we meet current number for the first time) or the counter that have
// the corresponding value equal to arr[i]
for(; counts[index_of_counter].counter != 0 && counts[index_of_counter].number != arr[i]; index_of_counter++)
; // Do nothing here - index_of_counter is incrementing in loop-statement
// We found an index of our counter
// Let's assign the value (it will assign a value
// to newly initialized pair and won't change anything
// in case of already existing value).
counts[index_of_counter].number = arr[i];
// Increment our counter. It'll became 1 in case of new
// counter, because of zero assigned to it a bit above.
counts[index_of_counter].counter += 1;
}
// Now let's iterate over all counters until we reach the first
// containing zero (it means that this counter and all after it are not used)
for(size_t i = 0; i < length && counts[i].counter > 0; i++) {
std::cout << counts[i].number << " appeared " << counts[i].counter << " times\n";
}
// correctly delete dynamically allocated memory
delete[] counts;
delete[] arr;
https://godbolt.org/z/hN33Pn
Moreover it is exactly the same solution like with std::map (the same idea), so I hope it can help you to understand, how the first solution works inside
The problem with your code is that you don't remove the duplicates or assign an array which effectively stores the count of each unique element in your array.
Also the use of so many loops is completely unnecessary.
You just need to implement two loops, outer one going through all the elements and the inner one checking for dupes first (using an array to check frequency/occurence status) and counting appearance of each element seperately with a variable used as a counter.
Set a counter array (with the corresponding size of your taken array) with a specific value (say zero) and change that value when same element occurs while traversing the array, to trigger not to count for that value again.
Then transfer the count value from the counter variable to the counter array (the one which we set and which distinguishes between duplicates) each time the inner loop finishes iterating over the whole array. (i.e. place it after the values are counted)
With a little bit of modification, your code will work as you would want it to:
#include <iostream>
using namespace std;
int main()
{
int n;
cout<<"Enter Length of Elements = ";
cin>>n;
int arr[50];
for(int i=0;i<n;i++)
{
cout<<"Enter Number = ";
cin>>arr[i];
}
int counter[50];
for(int i=0; i<n; i++)
counter[i]=0;
// Our counter variable, but counts will be transferred to count[] later on:
int tempcount;
for(int i=0; i<n; i++)
{ // Each distinct element occurs once atleast so initialize to one:
tempcount = 1;
for(int j=i+1; j<n; j++)
{
// If dupe is found:
if(arr[i]==arr[j])
{
tempcount++;
// Ensuring not to count frequency of same element again:
counter[j] = 1;
}
}
// If occurence of current element is not counted before:
if(counter[i] != 1)
counter[i] = tempcount;
}
for(int i=0; i<n; i++)
{
if(counter[i] != 0)
printf("%d has appeared %d times.\n", arr[i], counter[i]);
}
return 0;
}
I used a variable tempcount to count occurence of each element and a zero-initialized array count to get the dupes checked (by setting it to 1 for a duplicate entry, and not counting it if it qualifies as 1) first. Then I transferred the counted occurence values to counter[] from tempcount at each outer loop iteration. (for all the unique elements)

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.

Given a vector with integers from 0 to n, but not all included, how do I efficiently get the non-included integers?

Given a vector with integers from 0 to n, but not all included, how do I efficiently get the non-included integers?
For example if I have a vector with 1 2 3 5, I need to get the vector that contains 0 4.
But I need to do it very efficiently.
Since the vector is already sorted, this becomes trivial:
vector<int> v = {1,2,3,5};
vector<int> ret;
v.push_back(n+1); // this is to enforce a limit using less branches in the loop
for(int i = 0, j = 0; i <= n; ++i){
int present = v[j++];
while(i < present){
ret.push_back(i++);
}
}
return ret;
Additionally, if it wasn't sorted, you could either sort it and apply the above algorithm, or, if you know the range of n, and you can afford the extra memory, you could instead create an array of boolean (or a bitset) and mark the index corresponding to every element you encounter (e.g. bitset[v[j++]] = true;), subsequently iterating from 0 to n and inserting into your vector every element whose bitset position has not been marked.
Basically the idea presented here is that we know the number of missing items beforehand if we can assume sorted input without duplicate values.
Then it is possible to pre-allocate enough space to hold the missing values beforehand (no later dynamic allocation required). Then we can also exploit the possible shortcut when all missing values were found.
If the input vector is not sorted or contains duplicate values, a wrapper function can be used that establishes this precondition.
#include <iostream>
#include <set>
#include <vector>
inline std::vector<int> find_missing(std::vector<int> const & input) {
// assuming non-empty, sorted input, no duplicates
// number of items missing
int n_missing = input.back() - input.size() + 1;
// pre-allocate enough memory for missing values
std::vector<int> result(n_missing);
// iterate input vector with shortcut if all missing values were found
auto input_it = input.begin();
auto result_it = result.begin();
for (int i = 0; result_it != result.end() && input_it != input.end(); ++i) {
if (i < *input_it) (*result_it++) = i;
else ++input_it;
}
return result;
}
// use this if the input vector is not sorted/unique
inline std::vector<int> find_missing_unordered(std::vector<int> const & input) {
std::set<int> values(input.begin(), input.end());
return find_missing(std::vector<int>(values.begin(), values.end()));
}
int main() {
std::vector<int> input = {1,2,3,5,5,5,7};
std::vector<int> result = find_missing_unordered(input);
for (int i : result)
std::cout << i << " ";
std::cout << "\n";
}
The output is:
$ g++ test.cc -std=c++11 && ./a.out
0 4 6