Finding most frequent odd number in vector? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have ant task, to search most frequent odd number in vector array. I cant figure it out.
this is, how i am writing data, to array
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
class oddNum {
private:
vector <int> numbers;
int number, n;
public:
void getData() {
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> number;
if(number % 2 != 0) {
numbers.push_back(number);
}
}
}
};
int main() {
oddNum n;
n.getData();
return 0;
}
my numbers
8 5 5 1 3

There are several ways to do it, I show you two. The first one is not intuitive and requires quite the bookmarking. However, the last solution uses the modern containers and their nature to do this in an elegant style.
First you sort the vector. This way all equal elements are next to each other. Than you iterate through this vector to look for the largest pack of elements while skipping all even numbers. Create a variable counter which resets if the elements change (this can be done by comparing the current element to the next element of the array) and a max variable that holds the largest value of said counter. Whenever this counter exceeds the value of max you have found the most common element so far which can be saved in a variable result. When you're done iterating, the variable result will contain the most frequent odd element of the vector. This implementation, in addition to <vector>, also needs the <algorithm> and <cassert> headers.
int get_most_frequent_odd(const std::vector<int>& vec) {
assert(!vec.empty());
std::vector<int> sorted = vec;
std::sort(sorted.begin(), sorted.end());
unsigned counter = 0u;
unsigned max = 0u;
int result;
for (unsigned i = 0u; i < sorted.size() - 1; ++i) {
if (sorted[i] % 2 != 0) {
if (sorted[i] == sorted[i + 1]) {
++counter;
if (max < counter) {
max = counter;
counter = 0u;
result = sorted[i];
}
}
else {
counter = 0u;
}
}
}
return result;
}
The function is quite specific (only for int's and odd elements). Also your getData() function already sorts out all even numbers. So here's a more generic function get_most_frequent<T>:
template<typename T>
T get_most_frequent(const std::vector<T>& vec) {
assert(!vec.empty());
std::vector<T> sorted = vec;
std::sort(sorted.begin(), sorted.end());
unsigned counter = 0u;
unsigned max = 0u;
T result;
for (unsigned i = 0u; i < sorted.size() - 1; ++i){
if (sorted[i] == sorted[i + 1]) {
++counter;
if (max < counter) {
max = counter;
counter = 0u;
result = sorted[i];
}
}
else {
counter = 0u;
}
}
return result;
}
Now a std::unordered_map or std::map will be superior over a std::vector for this task as they are build in a way that allows you to skip this ugly bookmarking. It's way more readable, too. But given you said you are a beginner I didn't put this at first place. The idea is to count the frequency by using a std::unordered_map. The elements are set to be the keys of the map and incrementing the values behind the keys will give you the occurrency of the elements. (Thanks #YSC) You can now use std::max_element which will return the pair with the highest saved occurrence. This implementation requires the <unordered_map>, <utility>, <algorithm> and <cassert> headers.
template<typename T>
T get_most_frequent(const std::vector<T>& vec) {
std::unordered_map<T, int> frequency_map;
for (auto i : vec) {
++frequency_map[i];
}
return std::max_element(frequency_map.begin(), frequency_map.end())->first;
}
example run using either of these 3 functions:
how many numbers?: 8
input number 1: 5
input number 2: 5
input number 3: 4
input number 4: 9
input number 5: 9
input number 6: 9
input number 7: 11
input number 8: 0
most common element is: 9
full code:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <cassert>
template<typename T>
T get_most_frequent(const std::vector<T>& vec) {
std::unordered_map<T, int> frequency_map;
for (auto i : vec) {
++frequency_map[i];
}
return std::max_element(frequency_map.begin(), frequency_map.end())->first;
}
class oddNum {
private:
std::vector<int> numbers;
public:
void getData() {
std::size_t size;
std::cout << "how many numbers?: ";
std::cin >> size;
int number;
for (int i = 0; i < size; ++i) {
std::cout << "input number " << i + 1 << ": ";
std::cin >> number;
if (number % 2 != 0) {
numbers.push_back(number);
}
}
std::cout << "most common element is: " << get_most_frequent(numbers) << '\n';
}
};
int main() {
oddNum n;
n.getData();
}

Related

give how many numbers in a vector that are less than itself

i have to find how many other numbers are less than nums[i] and return them in another vector, for example [6,5,4,8] nums[0] = 6 so there is two numbers less than 6. so 2 would be pushed to the other vector. i am not getting 3 when it comes to checking the last element
class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> nums2;
for(int i =0; i< nums.size(); ++i){
int max = nums[i];
int count = 0;
for(int j =0; j < nums.size(); ++j){
if(nums[j] < max && j!=0)
count++;
else
continue;
}
nums2.push_back(count);
}
return nums2;
}
};
You exclude the first element when counting in the condition:
if(nums[j] < max && j!=0)
// ^^ ---- remove this
There are algorithms that do want you need. std::transform transforms one range of values to another one and count_if counts how often a predicate returns true for a given range:
#include <vector>
#include <iostream>
#include <algorithm>
std::vector<size_t> count_if_smaller(const std::vector<int>& v) {
std::vector<size_t> result(v.size());
std::transform(v.begin(),v.end(),result.begin(),
[&](int x){
return std::count_if(v.begin(),v.end(),[&](int y){
return y < x;
});
} );
return result;
}
int main() {
std::vector<int> v{6,5,4,8};
auto r = count_if_smaller(v);
for (auto e : r) std::cout << e << " ";
}
One advantage of using algorithms is that you need not bother about indices of single elements. Introducing the same bug as in your code would be more difficult in the above. In other words, using algorithms is less error prone. Consider to use them when you can.
PS: Your current approach has complexity O(N^2). If you sort the input vector you could get O(N log N) easily.

Repeating elements in vector

I am a C++ student. And I need to solve this problem: "Write a program that receives a number and an array of the size of the given number. The program must find all the duplicates of the given numbers, push-back them to a vector of repeating elements, and print the vector". The requirements are I'm only allowed to use the vector library and every repeating element of the array must be pushed to the vector only once, e.g. my array is "1, 2, 1, 2, 3, 4...", the vector must be "1 ,2".
Here's what I've done so far. My code works, but I'm unable to make it add the same duplicate to the vector of repeating elements only once.
#include <iostream>
#include <vector>
int main() {
int n;
std::cin >> n;
int* arr = new int[n];
std::vector<int> repeatedElements;
for(int i = 0; i < n; ++i) {
std::cin >> arr[i];
}
for(int i = 0; i < n; ++i) {
bool foundInRepeated = false;
for(int j = 0; j < repeatedElements.size(); ++j) {
if(arr[i] == repeatedElements[j]) {
foundInRepeated = true;
break;
}
}
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) {
int count = 1;
for(int j = i + 1; j < n; ++j) {
if(arr[i] == arr[j]) {
++count;
}
}
if(count > 1) {
repeatedElements.push_back(arr[i]);
}
}
}
}
for(int i = 0; i < repeatedElements.size(); ++i) {
std::cout << repeatedElements[i] << " ";
}
std::cout << std::endl;
}
Consider what you're doing here:
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) { // why?
If the element at some index i (from the outer loop) is not found in repeatedElements, you're again iterating through the entire array, and adding elements that are repeated. But you already have an i that you're interested in, and hasn't been added to the repeatedElements. You only need to iterate through j in the else branch.
Removing the line marked why? (and the closing brace), will solve the problem. Here's a demo.
It's always good to follow a plan. Divide the bigger problem into a sequence of smaller problems is a good start. While this often does not yield an optimal solution, at least it yields a solution, which is more or less straightforward. And which subsequently can be optimized, if need be.
How to find out, if a number in the sequence has duplicates?
We could brute force this:
is_duplicate i = arr[i+1..arr.size() - 1] contains arr[i]
and then write ourselves a helper function like
bool range_contains(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last, int value) {
// ...
}
and use it in a simple
for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter) {
if (range_contains(iter+1, arr.cend(), *iter) && !duplicates.contains(*iter)) {
duplicates.push_back(*iter);
}
}
But this would be - if I am not mistaken - some O(N^2) solution.
As we know, sorting is O(N log(N)) and if we sort our array first, we will
have all duplicates right next to each other. Then, we can iterate over the sorted array once (O(N)) and we are still cheaper than O(N^2). (O(N log(N)) + O(N) is still O(N log(N))).
1 2 1 2 3 4 => sort => 1 1 2 2 3 4
Eventually, while using what we have at our disposal, this could yield to a program like this:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using IntVec = std::vector<int>;
int main(int argc, const char *argv[]) {
IntVec arr; // aka: input array
IntVec duplicates;
size_t n = 0;
std::cin >> n;
// Read n integers from std::cin
std::generate_n(std::back_inserter(arr), n,
[](){
return *(std::istream_iterator<int>(std::cin));
});
// sort the array (in ascending order).
std::sort(arr.begin(), arr.end()); // O(N*logN)
auto current = arr.cbegin();
while(current != arr.cend()) {
// std::adjacent_find() finds the next location in arr, where 2 neighbors have the same value.
current = std::adjacent_find(current,arr.cend());
if( current != arr.cend()) {
duplicates.push_back(*current);
// skip all duplicates here
for( ; current != (arr.cend() - 1) && (*current == *(current+1)); current++) {
}
}
}
// print the duplicates to std::cout
std::copy(duplicates.cbegin(), duplicates.cend(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}

c++ random number duplicate prevent [duplicate]

This question already has answers here:
Create Random Number Sequence with No Repeats
(27 answers)
Closed 6 years ago.
I've got a random number generator function ("Rndom (min, max)"),
and I have an int with 4 elements called "Data [3]".
I used the for loop to generate numbers (1-4) to the elements of the "Data" int:
for (int i = 0;i < 3;i++)
{
Data[i] = Rndom(1, 4)
}
How can I prevent that the data gets duplicated element number ?
So, I don't want this: "Data" elements: 1 3 4 1 ("1" is duplicated). I want to make different numbers....
Thank you for the help !
Since you want an array or vector of shuffled integer values, use std::shuffle to shuffle a vector (or whatever) initialized with sequential values.
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <numeric>
int main() {
std::random_device rd;
std::mt19937 rng(rd()); // seed rng using rd
std::vector<int> data(3); // create a 3-entry vector
std::iota(data.begin(), data.end(), 0); // fill with sequence
std::shuffle(data.begin(), data.end(), rng); // mix entries using rng
// dump the result
for(auto r : data) { std::cout << r << ' '; }
std::cout << '\n';
}
The outputs of 3 executions:
1 0 2
2 1 0
2 0 1
Here is a version which doesn't rely so much on the standard C++ library, and uses the C-runtime's crappy random number generator, just because I didn't have access to Rndom's source code, which is undoubtedly of a proprietary nature, so this is quite understandable:
#include <iostream> // only for std::cout
#include <cstdlib> // for srand, rand
#include <ctime> // for time
namespace shuffle {
using size_t = decltype(sizeof(1));
bool Srndom() {
std::srand(std::time(0));
return true;
}
int Rndom(int low, int high) {
static bool init = Srndom();
return std::rand() % (high - low + 1) + low;
}
template <typename T>
void Shuffle(T* pdata, size_t N) {
for(size_t i=0; i<N-1; ++i) {
const int swap_idx = Rndom(i, N-1);
if(swap_idx != i) {
const T t = pdata[i];
pdata[i] = pdata[swap_idx];
pdata[swap_idx] = t;
}
}
}
template <typename T, size_t N>
void Shuffle(T (&data)[N]) {
Shuffle(data, N);
}
template <typename T>
void Series(T* pdata, size_t N, T start) {
for(size_t i=0; i<N; ++i) {
pdata[i] = start++;
}
}
template <typename T, size_t N>
void Series(T (&data)[N], T start) {
Series(data, N, start);
}
}
int main() {
using namespace shuffle;
int Data[4]; // I guess you actually want 4
Series(Data, 1); // and maybe to start at 1.
Shuffle(Data); // Shuffle Data's entries.
// Dump Data's entries
for(size_t i=0; i<sizeof(Data)/sizeof(Data[0]); ++i) {
std::cout << Data[i] << ' ';
}
std::cout << '\n';
}
The outputs of 3 executions (over 1 second apart):
2 3 1 4
4 2 3 1
2 4 3 1
Use map or set to store the numbers generated and avoid duplication.
set<int> s;
for (int i = 0;i < 3;i++)
{
int x;
for(;;)
{
int x = Rndom(1, 4) ;
if(s.find(x)==s.end())
{
s.insert(x);
Data[i]=x;
// consider it ..it is not duplicate
break;
}
}
}
Also you can use set or unordered_set to realize the same thing.
The reason of using set over map is std::sets contain only the key, while in std::map there is an associated value.

Find in which order original elements were removed from an array

I have a problem with the following task:
At the beginning you start with an array of n numbers from 1 to n. Then you remove entries one by one by choosing the index in the current array.
I am to output the order in which the original elements were removed.
For example:
Input:
6
1 4 4 2 2 1
Output:
1 5 6 3 4 2
Speed is important, so I need the solution to be as fast as possible. It seems it can be done in little-oh(n^2) but I don't know how. The solution has to be C++.
My correct, albeit too slow solution:
int n = 0;
std::cin >> n;
std::vector<int> nums(n);
std::iota(nums.begin(), nums.end());
for (int i = 0; i < n; ++i) {
int toRemove;
std::cin >> toRemove;
--toRemove;
std::cout << nums[toRemove] << " ";
nums.erase(nums.begin() + toRemove);
}
If you can change your container type from a vector to a list then you can avoid having to copy the elements every time you remove one. This should be much more efficient, however the increased complexity of the lookup bogs down this solution too much to be an improvement except in a nearly optimal case.
#include <vector>
#include <list>
#include <iostream>
#include <numeric>
#include <iterator>
template<typename T, template <typename, typename> class Container>
class LookupRemove {
typedef Container<T, std::allocator<T> > ContainerType;
public:
LookupRemove(int size):
remaining(size),
nums(size) {
std::iota(nums.begin(), nums.end(), 1);
}
T removePosition(T position) {
if (position < remaining) { // make sure advance doesn't go past end
auto pos = nums.begin();
std::advance(pos, position); // set the position to retrieve and remove
T value = *pos;
nums.erase(pos);
--remaining;
return value;
}
return 0;
}
private:
ContainerType nums;
T remaining;
};
int main() {
int n = 1000000;
LookupRemove<int, std::vector> lookupVector(n);
for (int i = 0; i < n; ++i) {
lookupVector.removePosition(0);
}
LookupRemove<int, std::list> lookupList(n);
for (int i = 0; i < n; ++i) {
lookupList.removePosition(0);
}
return 0;
}
Some time profiling measurements:
elements: 10000
vector: 5.0 ms
list: - ms
elements: 100000
vector: 639.0 ms
list: 1.0 ms
elements: 1000000
vector: 83022.0 ms
list: 25.0 ms
edit: This profiling is flawed because it's the optimal case for removing from a list, removing the first member every time. Profiling with random positions shows comparable times removing from a vector vs removing from a list.

range of numbers and show numbers repeat c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
You can help me with a different program. .. It introduces a range of numbers (no limit, you can repeat numbers) in which to display how many times each digit entered in..
Ex: 1 3 4 3 3 6 1
Result:
1-2x
3-3x
4-1x
6-1x
Thanks nice.
#include <iostream>
#include <cstdlib>
using namespace std;
int rnd()
{
int iRand = (rand() % 100) + 1;
}
int hundred_random()
{
for (int rCount=0; rCount < 100; ++rCount)
{
cout << rnd() << endl;
}
}
int main()
{
cout << " The list of Hundred random numbers are- " << endl;
hundred_random();
return 0;
}
In order to count how often each number occurs in a list of numbers, you can do the following:
#include <iostream>
#include <vector>
#include <map>
#include <cstdlib>
We need these headers for output, storing the numbers, storing the count, and rand() for generating the example.
std::vector<int> generate_numbers(int amount, int max_num)
{
std::vector<int> numbers(amount);
for (int i = 0; i < amount; ++i) {
numbers[i] = rand() % max_num + 1;
}
return numbers;
}
A helper method to generate a bunch of random numbers.
std::map<int, int> count_numbers(const std::vector<int> &numbers)
{
// Count numbers
std::map<int, int> counts; // We will store the count in a map for fast lookup (C++11's unordered_map has even faster lookup)
for (size_t i = 0; i < numbers.size(); ++i) { // For each number
counts[numbers[i]]++; // Add 1 to its count
}
return counts;
}
The above method does the counting, which is the essence of your question. For each number that we encounter, we increment its count.
void print_counts(const std::map<int, int> &counts)
{
for(std::map<int, int>::const_iterator it = counts.begin();
it != counts.end(); ++it) { // For each number stored in the map (this automatically filters those with count 0)
std::cout << it->first << ": " << it->second << std::endl; // Output its count
}
}
Finally, a method to display our results. Since we never acted on any numbers that occur zero times, they are not in the map and will be omitted from the output.
int main() {
srand(0); // So that we get the same result every time
std::vector<int> numbers = generate_numbers(10000, 500);
std::map<int, int> counts = count_numbers(numbers);
return 0;
}
And putting it all together. See this code run.