How to find minimum value from vector with some condition? - c++

I need to get the min element value (x) in a vector.
Given the index i of x, I need to check if flag[i] == 0 to return i.
I don't want to sort or discard any value because I need its ordinal number, I need the vector to hold its "structure".
How can I get the index of that minimum element?
A = {1, 2, 3, 4, 0, -1}
flag = {0, 0, 1, 0, 1, 1}
min_element = -1, but flag[5] = 1, same for element 0, so min_element should be 1 at index 0.
Ps: I want to shortest solution

You can have a filter view of A with only the elements where flag is 0, and pass that to std::ranges::min.
With C++23 range views:
namespace views = std::ranges::views;
// min is undefined if passed an empty range
assert(std::ranges::any_of(flag, [](auto f){ return f == 0; });
auto value = std::ranges::min(views::zip(A, flag)
| views::filter([](auto && item){ return std::get<1>(item) == 0; })
| views::transform([](auto && item){ return std::get<0>(item); }));
See it on godbolt

If you store both arrays in a single std::vector<std::pair<int,int>> you can use std::min_element directly:
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> A = {1, 2, 3, 4, 0, -1};
std::vector<int> flag = {0, 0, 1, 0, 1, 1};
std::vector<std::pair<int,int>> flag_and_A;
for (int i=0;i<A.size();++i){
flag_and_A.push_back({flag[i],A[i]});
}
auto it = std::min_element(flag_and_A.begin(),flag_and_A.end());
std::cout << it->second;
}
Live Demo
std::pair::operator< induces a lexicographical odering, ie first first (the flag) is compared then second (A). In other words, entries with flag == 0 are considered smaller than entries with flag == 1.
If you do not want to construct the vector<pair<int,int>> you can still use std::pair::operator< (more precisely the following uses std::tuple<int,int>::operator< which is basically the same):
#include <vector>
#include <iostream>
#include <algorithm>
#include <tuple>
int main() {
std::vector<int> A = {1, 2, 3, 4, 0, -1};
std::vector<int> flag = {0, 0, 1, 0, 1, 1};
auto it = std::min_element(A.begin(),A.end(),[&](const int& a,const int& b){
unsigned index_a = &a - &A[0];
unsigned index_b = &b - &A[0];
return std::tie(flag[index_a],a) < std::tie(flag[index_b],b);
});
std::cout << *it;
}
Live Demo

I think you can make a copy of the vector, to sort, record the min-element,and then clear the copy vector.

#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> A = {1, 2, 3, 4, 0, -1};
vector<int> flag = {0, 0, 1, 0, 1, 1};
size_t index = -1;
int min_value = 0;
for(size_t i = 0; i < A.size(); ++i) {
if ((flag[i] == 0) && (index == -1 || A[i] < min_value)) {
index = i;
min_value = A[i];
}
}
if (index == -1) {
cout << "not found";
}
else {
cout << "min is A[" << index << "]: " << A[index];
}
return 0;
}
Online demo

Related

Is there a binary search algorithm that takes a unary predicate rather than a search value?

I have this exercise:
Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.
For example, input [3, 4, -1, 1] should give 2 and input [1, 2, 0] should give 3.
You can modify the input array in-place.
 
My implementation:
template <typename In_It>
int missingPositiveInt(In_It first, In_It last){
first = std::find_if( first, last, [](int x){return x > 0;} );
if(first == last || *first > 1)
return 1;
for( auto next = first; (++next != last) && ( !(*next - *first > 1) ); )
++first;
return *first + 1;
}
int main(){
std::vector<int> v{5, 2, -1, 7, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {2, -1, 1, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {5, 2, -1, 7, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {3, 4, -1, 1};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
v = {1, 2, 0};
std::sort(v.begin(), v.end());
std::cout << missingPositiveInt(v.cbegin(), v.cend()) << '\n';
std::cout << '\n';
}
The output:
1
3
1
2
3
The program works just fine but I use the algorithm std::find_if to find the first positive value in the sequence (sorted sequence) and that algorithm does a linear search.
As long as the input sequence is already sorted I want to use some binary search algorithm to speed the process.
I tried using std::binary_search but it requires an argument to be searched for. What I need is to get a version that takes a unary predicate and applies a binary search or any other faster algorithm to find the lowest positive value in the sequence so I can write:
auto it = binary_search(first, last, [](int x){ return x > 0; });
Is it possible? Is my code fine or I need to modify it. So any suggestion, hint is highly appreciated.
Yes, std::partition_point does exactly what you want.
Partial solution based on #numzero's answer. This doesn't handle negative numbers or zero in the array but you can handle that by linearly preprocessing the array to remove them beforehand. It just marks each index as "found" by negating it, then later looks for the first non negative value and thats the one. Even though its a partial solution it shows the core algorithm.
#include <iostream>
using namespace std;
int main() {
int arr[] = {1, 4, 6, 7, 2, 7, 7, 8, 3};
int arrSize = sizeof(arr)/sizeof(int);
for(int i=0; i<arrSize; ++i)
{
int val = abs(arr[i]);
if(val > 0 && val-1 < arrSize)
{
if (arr[val-1]>0)
{
arr[val-1] = -arr[val-1];
}
}
}
for(int i=0; i<arrSize; ++i)
{
if(arr[i] > 0)
{
std::cout << "Smallest is " << (i+1) << std::endl;
return 0;
}
}
std::cout << "Nothing found!" << std::endl;
// your code goes here
return 0;
}

loop over map of vectors and get max across columns in c++

I have a map defined as follows:
const map<int, vector<float> >& m = …;
I want to loop over the columns (size of the map.second: vector) and in every iteration I get the:
1- The max value of the column across the map.first: int
2- The value of the map.first: int at the which the max occurs
For example:
#0 I get 31, 1
#1 I get 15, 2
#2 I get 18, 2
What is the easiest way to do this?
You need a function that accepts a column number and loops through each row calculating the maximum for that column.
You only need one loop because you can access whichever column you want by indexing the vector like an array (as long as you check that the vector has enough elements)
There are two ways to do this: the C++17 way where you can assign objects with multiple values directly to multiple variables, and the old way where you reference the members of std::pair instead.
The C++17 way:
#include <map>
#include <vector>
#include <utility>
#include <iostream>
std::pair<int,float> column_max(const auto & m, int column)
{
int index = -1;
float maximum = -std::numeric_limits<float>::max();
for (const auto & [key,value] : m)
if (value.size() > column && value[column] > maximum)
{
index = key;
maximum = value[column];
}
return {index,maximum};
}
int main()
{
const std::map<int,std::vector<float>> m =
{
{0, { 1, 5, 10, 22}},
{1, {31, 5, 10, 12}},
{2, { 1, 15, 18, 12}}
};
for (int i=0; i<4; i++)
{
const auto [index,maximum] = column_max(m,i);
std::cout << "#" << i << ": " << maximum << " " << index << "\n";
}
return 0;
}
Try it here: https://onlinegdb.com/O5dmPot34
And the equivalent, but older way:
#include <map>
#include <vector>
#include <utility>
#include <iostream>
#include <float.h>
std::pair<int,float> column_max(const std::map<int,std::vector<float>> & m, int column)
{
int index = -1;
float maximum = -FLT_MAX;
for (std::map<int,std::vector<float>>::const_iterator entry=m.begin(); entry!=m.end(); entry++)
if (entry->second.size() > column && entry->second[column] > maximum)
{
index = entry->first;
maximum = entry->second[column];
}
return std::make_pair(index,maximum);
}
int main()
{
const std::map<int,std::vector<float>> m =
{
{0, { 1, 5, 10, 22}},
{1, {31, 5, 10, 12}},
{2, { 1, 15, 18, 12}}
};
for (int i=0; i<4; i++)
{
std::pair<int,float> value = column_max(m,i);
std::cout << "#" << i << ": " << value.second << " " << value.first << "\n";
}
return 0;
}
Try it here: https://onlinegdb.com/273dnHRZK

Error in quicksort using Hoare partitioning with iterators, error with some specific small arrays

I am trying to make a C++ Quicksort algorithm using Hoare's partitioning. However I keep running into arrays that aren't sorted correctly, while most arrays sort OK. An example of such a troubling array is {1, 3, 0, 4, 3} which results in {0, 3, 1, 3, 4}.
The code contains the Quicksort code in the quicksort class, and fuzzy testing in the main function.
#include <iostream>
#include <random>
#include <vector>
class quicksort
{
public:
template <class random_access_iterator>
void operator()(random_access_iterator begin, random_access_iterator end)
{
quicksort_recursive_step(begin, end);
}
private:
template <class random_access_iterator>
void quicksort_recursive_step(random_access_iterator begin, random_access_iterator end)
{
if ((end - begin) <= 1)
{
return;
}
auto left = begin;
auto right = (end - 1);
const auto pivot = *(left + ((right - left) / 2));
while (left < right)
{
while (*left < pivot)
{
left++;
}
while (*right > pivot)
{
right--;
}
if (left < right)
{
std::iter_swap(left, right);
left++;
right--;
}
}
auto separator = (right + 1);
quicksort_recursive_step(begin, separator);
quicksort_recursive_step(separator, end);
}
};
int main()
{
std::random_device rd;
std::mt19937 eng{rd()};
std::uniform_int_distribution<int> size_dist{0, static_cast<int>(5)};
quicksort sorter;
std::vector<int> test = {0, 0, 4, 0, 1};
sorter(test.begin(), test.end());
bool has_error = false;
while (!has_error)
{
std::vector<int> test_array(size_dist(rd));
if (!test_array.empty())
{
std::uniform_int_distribution<int> values_dist{0, static_cast<int>(test_array.size() - 1)};
std::generate(test_array.begin(), test_array.end(), [&values_dist, &rd]() { return values_dist(rd); });
}
std::vector<int> original_test_array(test_array);
std::cout << "Sorting array of size " << test_array.size() << " ... ";
for (const auto& t : original_test_array)
{
std::cout << t << ", ";
}
std::cout << std::endl;
sorter(test_array.begin(), test_array.end());
bool is_permutation = std::is_permutation(test_array.begin(), test_array.end(), original_test_array.begin());
bool is_sorted = std::is_sorted(test_array.begin(), test_array.end());
if (is_permutation && is_sorted)
{
std::cout << "OK" << std::endl;
}
else
{
has_error = true;
std::cout << "ERROR!" << std::endl;
std::cout << "Array was: ";
for (const auto& t : original_test_array)
{
std::cout << t << ", ";
}
std::cout << std::endl;
std::cout << "Result is: ";
for (const auto& t : test_array)
{
std::cout << t << ", ";
}
std::cout << std::endl;
}
}
return 0;
}
Possible output (error at the bottom):
Sorting array of size 0 ...
OK
Sorting array of size 2 ... 0, 1,
OK
Sorting array of size 5 ... 1, 2, 2, 0, 0,
OK
Sorting array of size 5 ... 4, 1, 3, 0, 0,
OK
Sorting array of size 5 ... 2, 2, 2, 4, 1,
OK
Sorting array of size 5 ... 1, 3, 3, 3, 1,
OK
Sorting array of size 4 ... 1, 0, 1, 3,
OK
Sorting array of size 1 ... 0,
OK
Sorting array of size 1 ... 0,
OK
Sorting array of size 3 ... 0, 2, 0,
OK
Sorting array of size 4 ... 0, 2, 1, 1,
OK
Sorting array of size 3 ... 0, 1, 1,
OK
Sorting array of size 4 ... 3, 1, 3, 1,
OK
Sorting array of size 4 ... 3, 2, 3, 3,
OK
Sorting array of size 2 ... 0, 0,
OK
Sorting array of size 4 ... 3, 3, 3, 1,
OK
Sorting array of size 3 ... 0, 2, 0,
OK
Sorting array of size 3 ... 0, 0, 2,
OK
Sorting array of size 1 ... 0,
OK
Sorting array of size 5 ... 2, 3, 4, 1, 3,
OK
Sorting array of size 3 ... 1, 1, 0,
OK
Sorting array of size 3 ... 1, 0, 2,
OK
Sorting array of size 3 ... 1, 0, 2,
OK
Sorting array of size 1 ... 0,
OK
Sorting array of size 4 ... 0, 3, 3, 3,
OK
Sorting array of size 0 ...
OK
Sorting array of size 5 ... 4, 1, 3, 1, 0,
OK
Sorting array of size 3 ... 2, 2, 1,
OK
Sorting array of size 0 ...
OK
Sorting array of size 2 ... 1, 1,
OK
Sorting array of size 0 ...
OK
Sorting array of size 2 ... 0, 1,
OK
Sorting array of size 2 ... 0, 1,
OK
Sorting array of size 2 ... 0, 0,
OK
Sorting array of size 5 ... 3, 0, 0, 3, 3,
OK
Sorting array of size 3 ... 0, 1, 2,
OK
Sorting array of size 2 ... 1, 0,
OK
Sorting array of size 3 ... 0, 2, 1,
OK
Sorting array of size 3 ... 1, 1, 0,
OK
Sorting array of size 0 ...
OK
Sorting array of size 4 ... 0, 3, 0, 2,
OK
Sorting array of size 0 ...
OK
Sorting array of size 2 ... 0, 0,
OK
Sorting array of size 0 ...
OK
Sorting array of size 1 ... 0,
OK
Sorting array of size 0 ...
OK
Sorting array of size 5 ... 4, 0, 1, 1, 3,
OK
Sorting array of size 0 ...
OK
Sorting array of size 5 ... 1, 3, 0, 4, 3,
ERROR!
Array was: 1, 3, 0, 4, 3,
Result is: 0, 3, 1, 3, 4,
How can I solve this error? Everytime I try to solve it, I break something else. I also can't find good examples combining Hoare's partitioning and iterators as Lomuto's partitioning is mostly used in educational literature. I also want to avoid using std::partition etc.
A typical post-increment and post-decrement version of Hoare partition scheme similar to what is used in the question, has to compensate for the possibility that the right index may be decremented below the beginning of the array.
As an alternative, this example code uses a pre-increment and pre-decrement version of Hoare partition scheme, except that it skips decrementing then incrementing the left (b in the code below) iterator, using a goto to jump into the middle of the two partitioning loops. I could change the code to avoid goto, but an optimizing compiler is probably going to compile as if the goto was there as in my source code. For an even number of elements, it uses the left middle element for pivot (p = *(b+(e-b-1)/2)).
#include <iostream>
#include <iterator>
#include <vector>
void QuickSort(std::vector<int>::iterator b, std::vector<int>::iterator e)
{
std::vector<int>::iterator i = b;
std::vector<int>::iterator j = e;
int p = *(b+(e-b-1)/2);
if((e-b) < 2)
return;
if(*i >= p)
goto loop0;
while(1){
while (*(++i) < p);
loop0:
while (*(--j) > p);
if (i >= j)
break;
std::swap(*i, *j);
}
j++;
QuickSort(b, j);
QuickSort(j, e);
}
int rnd32() /* random number */
{
static unsigned int r = 0u;
r = r * 1103515245u + 12345u;
return (int)r;
}
#define COUNT (1024)
int main(int argc, char**argv)
{
size_t i;
std::vector <int> a(COUNT);
for(i = 0; i < COUNT; i++)
a[i] = rnd32();
QuickSort(a.begin(), a.end());
for(i = 1; i < COUNT; i++){
if(a[i-1] > a[i])
break;
}
if(i == COUNT)
printf("passed\n");
else
printf("failed\n");
return(0);
}
I've found an answer to my own question. In my code, when the left and right iterators are exchanged and then cross each other, I end my while loop. Thus, it is swap(lef,right), left++, right-- and stop. However, the algorithm should do the while(*left < pivot){left++;} and while (*right > pivot){right--;} loops once more to set the separator at the right spot. This wasn't immediately obvious to me looking at CLRS's pseudocode, but there the while loops are also executed once more before the return.
HOARE-PARTITION(A, p, r)
x = A[p]
i = p - 1
j = r + 1
while TRUE
repeat
j = j - 1
until A[j] <= x
repeat
i = i + 1
until A[i] >= x
if i < j
exchange A[i] with A[j]
else
return j
The correct code is thus:
template <class T>
class quicksort
{
public:
template <class random_access_iterator>
void operator()(random_access_iterator begin, random_access_iterator end)
{
quicksort_recursive_step(begin, end);
}
private:
template <class random_access_iterator>
void quicksort_recursive_step(random_access_iterator begin, random_access_iterator end)
{
assert(begin <= end);
if ((end - begin) <= 1)
{
return;
}
auto left = begin;
auto right = (end - 1);
auto middle = (left + ((right - left) / 2));
const auto pivot = *middle;
while (*left < pivot)
{
left++;
}
while (*right > pivot)
{
right--;
}
while (left < right)
{
std::iter_swap(left, right);
left++;
while (*left < pivot)
{
left++;
}
right--;
while (*right > pivot)
{
right--;
}
}
auto bound = (right + 1);
quicksort_recursive_step(begin, bound);
quicksort_recursive_step(bound, end);
}
};

What's wrong with this recursion method? Count number of matching elements that are in same index in 2 vectors

I'm trying to debug this program to find the number of matching elements that occur at the same index in 2 different vectors. Requirement is to NOT use any loops
Code on online compiler: http://cpp.sh/8rvtj
#include <iostream>
#include <vector>
using namespace std;
int calls=0;
int matchCount(const vector<int>& v1, const vector<int>& v2, int i=0)
{
calls++;
static int smallVecSz=-1;
smallVecSz = (v1.size()<v2.size() ? v1.size() : v2.size());
static int ans=0;
if(i==smallVecSz)
{
cout << "Returning " << ans << endl;
return ans;
}
// if element at index i is same in v1 and v2, add 1 to ans else add 0 to ans
ans += (v1[i]==v2[i] ? 1 : 0);
return ans + matchCount(v1,v2,i+1); // pass optional param index i+1 to advance to next ele
}
int main()
{
vector<int> v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector<int> v2 = {2, 5, 3, 0, 8, 4, 1};
cout << "There are " << matchCount(v1,v2) << " matching numbers at same indexes" << endl;
cout << "Number of Recursion calls: " << calls << endl;
return 0;
}
Here is a sample input:
vector v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector v2 = {2, 5, 3, 0, 8, 4, 1};
Here is a sample output:
Returning 4
There are 32 matching numbers at same indexes
Number of Recursion calls: 8
My program is recursive function is correctly returning the ans 4. But the main program is printing 32.
Oops, a static variable accumulating in a recursive function is a code smell.
Normally, when you use recursion, each call starts with a clean an fresh environment.
In that case, you accumulate the value of each call with its children to find the total.
Alternatively, you can use a static variable which is updated by each call and just used by the top parent.
But here you are mixing both approaches, actually getting a much too high value.
So 2 ways here:
make ans an automatic (non static) variable:
...
smallVecSz = (v1.size()<v2.size() ? v1.size() : v2.size());
int ans=0;
if(i==smallVecSz)
...
keep ans static, and do not accumulate:
...
ans += (v1[i]==v2[i] ? 1 : 0);
matchCount(v1, v2, i+1); // pass optional param index i+1 to advance to next ele
return ans;
...
Of course in that case, you will get wrong results if you call the function more than once because ans will not be reset to 0 (Thanks to #bruno for noticing)
your problem comes from ans being static and the fact you return it when you reach the end of the vector rather than 0 etc
I do not understand too why that function is recursive
a solution with a loop and an other with recursion as you requested in a comment
#include <iostream>
#include <vector>
using namespace std;
int matchCount(const vector<int>& v1, const vector<int>& v2)
{
vector<int>::const_iterator it1;
vector<int>::const_iterator it2;
int result = 0;
for (it1 = v1.begin(), it2 = v2.begin();
(it1 != v1.end()) && (it2 != v2.end());
++it1, ++it2) {
if (*it1 == *it2)
result += 1;
}
return result;
}
int recurMatchCount(const vector<int>& v1, const vector<int>& v2, int i = 0)
{
return ((i == v1.size()) || (i == v2.size()))
? 0
: (((v1[i] == v2[i]) ? 1 : 0)
+ recurMatchCount(v1, v2, i + 1));
}
int main()
{
vector<int> v1 = {2, 5, 2, 1, 8, 9, 1, 6, 9, 2};
vector<int> v2 = {2, 5, 3, 0, 8, 4, 1};
cout << "There are " << matchCount(v1,v2) << " matching numbers at same indexes" << endl;
cout << "There are " << recurMatchCount(v1,v2) << " recur matching numbers at same indexes" << endl;
return 0;
}

Finding the lowest missing integer in a vector containing positive and negative int's?

I'm writing an operation to find the lowest missing element of a vector, V = 1..N + 1. This has to be performed in O(N) time complexity.
Solution One:
std::vector<int> A {3,4,1,4,6,7};
int main()
{
int max_el = *std::max_element(A.begin(), A.end()); //Find max element
std::vector<int> V(max_el);
std::iota(V.begin(), V.end(), 1) //Populate V with all int's up to max element
for(unsigned into i {0}; i < A.size(); i++)
{
int index = A[i] - 1;
if(A[i] == V[index]) //Search V in O(1)
{
V[index] = max_el; //Set each to max_el, leaving the missing int
}
}
return *std::min_element(V.begin(), V.end()); //Find missing int as its the lowest (hasn't been set to max_el)
}
//Output: 2
This works completely fine.
However, I'm now trying to get this to work with vector containing negative int's.
Solution Two:
My logic is to take the same approach, however 'weight' the indexes given the size of the vector and the number of negative int's in the vector:
std::vector<int> A {-1, -4, -2, 0, 3, 2, 1}
int main()
{
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int min_el_abs = abs(min_el); //Convert min element to absolute
int total = min_el_abs + max_el;
std::vector<int> V(total + 1);
std::iota(V.begin(), V.end(), min_el);
int index;
//Find amount of negative int's
int first_pos;
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] >= 0) {first_pos = i; break;}
}
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] <= 0) //If negative
{
index = (A.size() - first_pos) - abs(A[i]);
} else
{
index = (A[i] + 1) + first_pos;
}
if(A[i] == V[index])
{
V[index] = 0;
}
}
return *std::min_element(V.begin(), V.end());
}
//Output: -3
Solution Two fails to compare the values of the two vectors (A and V), as calculating the index with the above methods with a positive int doesn't work.
1) How can I get my Solution 2 to work with unordered vector's of negative int's?
2) How can I edit my Solution 2 to work with vectors of positive as well as vectors with negative int's?
Your first solution seems O(max(N,M)), where I consider N the number of elements in vector A and M the size of vector V (or max(Ai)), but you are looping through both vectors multiple times (with std::min_element, std::max_element, the for loop, the allocation of V and std::iota too).
Besides, once corrected a couple of typos (a missing ; and an into instead of int), your program returns the value found... from main(), which is a bit odd.
Your first algorithm always searches for the lowest missing value in the range [1, max value in A], but it can be generalized to find the lowest missing element in the range [min(Ai), max(Ai)], even for negative numbers.
My approach is similar to that of L.Senioins, but I've used different library functions trying to minimize the number of loops.
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
template <class ForwardIt>
typename std::iterator_traits<ForwardIt>::value_type
lowest_missing(ForwardIt first, ForwardIt last)
{
if ( first == last )
throw std::string {"The range is empty"};
// find both min and max element with one function
auto result = std::minmax_element(first, last);
// range is always > 0
auto range = *result.second - *result.first + 1;
if ( range < 2 )
throw std::string {"Min equals max, so there are no missing elements"};
std::vector<bool> vb(range); // the initial value of all elements is false
for (auto i = first; i != last; ++i)
vb[*i - *result.first] = true;
// search the first false
auto pos = std::find(vb.cbegin(), vb.cend(), false);
if ( pos == vb.cend() ) // all the elements are true
throw std::string {"There are no missing elements"};
return std::distance(vb.cbegin(), pos) + *result.first;
}
template <class ForwardIt>
void show_the_first_missing_element(ForwardIt first, ForwardIt last)
{
try
{
std::cout << lowest_missing(first, last) << '\n';
}
catch(const std::string &msg)
{
std::cout << msg << '\n';
}
}
int main() {
std::vector<int> a { 1, 8, 9, 6, 2, 5, 3, 0 };
show_the_first_missing_element(a.cbegin(), a.cend());
std::vector<int> b { -1, -4, 8, 1, -3, -2, 10, 0 };
show_the_first_missing_element(b.cbegin(), b.cend());
show_the_first_missing_element(b.cbegin() + b.size() / 2, b.cend());
std::vector<int> c { -2, -1, 0, 1, 2, 3 };
show_the_first_missing_element(c.cbegin(), c.cend());
std::vector<int> d { 3, 3, 3 };
show_the_first_missing_element(d.cbegin(), d.cend());
std::vector<int> e;
show_the_first_missing_element(e.cbegin(), e.cend());
return 0;
}
The results outputted for my test cases are:
4
2
-1
There are no missing elements
Min equals max, so there are no missing elements
The range is empty
My solution is to make a bool vector (or char vector just to avoid compilation warnings about casting to bool) which has the size of all possible elements. All elements are initialized to 0 and later are assigned to 1 which indicates that the element is not missing. All you need to do then is to find an index of the first 0 element which is the lowest missing element.
#include <vector>
#include <algorithm>
#include <iostream>
std::vector<int> A{ -1, 0, 11, 1, 10, -5 };
int main() {
if (A.size() > 1) {
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int range = abs(max_el - min_el) + 1;
std::vector<int> V(range, 0);
for (size_t i = 0; i < A.size(); i++)
V[A[i] - min_el] = 1;
if (*std::min_element(V.begin(), V.end()) == 0)
std::cout << std::distance(V.begin(), std::find(V.begin(), V.end(), 0)) + min_el;
else
std::cout << "There are no missing elements" << std::endl;
}
else
std::cout << "There are no missing elements" << std::endl;
std::cin.get();
}
I'm going to try give my own question an answer, after spending sometime thinking about this:
int main()
{
std::vector<int> A {-3, -1, 0, 1, 3, 4};
auto relative_pos = std::minmax_elment(A.begin(), A.end());
std::vector<bool> Litmus( *(relative_pos.second) - *(relative_pos.first), false); //Create vector of size max val - min val)
auto lowest_val = *(relative_pos.first);
for(auto x : A)
{
Litmus[i - lowest_val] = true;
}
auto pos = std::find(Litmus.begin(), Litmus.end(), false); //Find the first occurring false value
std::cout<< (pos - Litmus.begin()) + lower<<std::endl; //Print the val in A relative to false value in Litmus
}
This solution works with negative numbers and is linear.
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <numeric>
int solution(vector<int> &A) {
std::vector<int>::iterator it = std::max_element(A.begin(),A.end());
try
{
sort(A.begin(),A.end());
std::vector<int>::iterator it = std::unique(A.begin(),A.end());
A.resize(std::distance(A.begin(),it));
for(int i = 0, j = 1; i < A.size(); i++)
{
if( A[i] != j)
{
return j;
}
j++;
}
}
catch(exception &e)
{
std::cout<<e.what()<<std::endl;
}
return ++(*it);
}