C++: Fastest method to check if all array elements are equal - c++

What is the fastest method to check if all elements of an array(preferable integer array) are equal. Till now I have been using the following code:
bool check(int array[], int n)
{
bool flag = 0;
for(int i = 0; i < n - 1; i++)
{
if(array[i] != array[i + 1])
flag = 1;
}
return flag;
}

int check(const int a[], int n)
{
while(--n>0 && a[n]==a[0]);
return n!=0;
}

Here is a solid solution which is valid C++11.
The advantages is that you do not need to manually play with the indexes or iterators. It is a best practice to
prefer algorithm calls to handwritten loops [Herb Sutter - C++ Coding Standards]
I think this will equally efficient as Paul R's solution.
bool check(const int a[], int n)
{
return !std::all_of(a, a+n, [a](int x){ return x==a[0]; });
}

Once you have found a mismatching element you can break out of the loop:
bool check(const int array[], int n)
{
for (int i = 0; i < n - 1; i++)
{
if (array[i] != array[i + 1])
return true;
}
return false;
}
If this is performance-critical then it can be further optimised slightly as:
bool check(const int array[], int n)
{
const int a0 = array[0];
for (int i = 1; i < n; i++)
{
if (array[i] != a0)
return true;
}
return false;
}

Recast the array to a larger data type. Eg, operate on 64bit ints, or use SSE or AVX intrinsics for 128 or 256 bit operation. For example, the SSE2 intrinsic is _mm_cmpeq_epi32, whose result you'll use with _mm_or_si128. Check the result with repeated application of _mm_srli_si128 and _mm_cvtsi128_si32. Check the result every few hundred iterations for early exit.
Make sure to operate on aligned memory, check the unaligned start and end as ints, and check the first packed element with itself.

For programmer efficiency you may try the following all in one line.
vector<int> v{1, 1, 1, 1};
all_of(v.cbegin(), v.cend(), [&r=v[0]](int value){ return value == r; }->bool);
I did not test run this code, let me know if there is syntax error.

Find a library that's available on your platform that supports threading or parallel-for loops, and split the computation out such that different cores test different ranges of the array.
Some available libraries are listed here:
http://parallel-for.sourceforge.net/parallelfor.html
Or possibly, you can make use of the parallism that many GPU's offer.

bool check(int array[],int n)
{
// here 1st element is checked with others. This decreases the number of iteration by 1.
// also it returns immediately.
// The requirement is to check if all the elements are equal.
// So if 1st element is equal to others then all elements are equal.
// Otherwise the elements are not equal.
for(int i=1;i<n;i++)
{
if(array[0]!=array[i])
return false;
}
return true;
}

We'll it's basically an O(n) operation so you can't do much better than what you have, other than dispensing with the flag and just return false; on the first failure and return true; after the iteration.

In theory, I would propose this:
bool check_single(const int a[], int n)
{
for (int i = 1; i < n; ++i) {
if (a[0] != a[n]) { return false; }
}
return true;
}
Compared to other (already proposed) versions:
a[0] will be hoisted outside the loop by the compiler, meaning a single array access within the loop
we loop from 0 to n, which is better (access-wise) than loading a[0] and then looping from a[n]
Obviously, it still checks N elements and thus is O(N).

fast hash mapping technique:
bool areSame(int a[],int n)
{
unordered_map<int,int> m; //hash map to store the frequency od every
for(int i=0;i<n;i++)
m[a[i]]++;
if(m.size()==1)
return true;
else
return false;
}

I think the following is more readable than the highest rated answer and I would wager more efficient too (but havent benchmarked)
bool check(int a[], int n)
{
if (n)
{
auto first = a[0];
for(int i = 1; i < n; i++)
{
if(array[i] != first) return false;
}
return true;
}
return true; //change to false for the OPs logic. I prefer logical true here
}

bool check_identity (int a[], int b[], const int size)
{
int i;
i = 0;
while ((i < size-1) && (a[i] == b[i])) i++;
return (a[i] == b[i]);
}

Related

What is the proper way to determine if any duplicate elements are present between multiple arrays in C++

I am having an issue trying to determine if my arrays contain any duplicate integers. For my Lo Shu Magic Square project, we are to create three different 1-dimensional arrays along with different functions to determine if the input is magic square numbers. I was able to make all other functions work but I cant seem to figure out how to check if the combined array inputs are all unique. Can anyone help? Here is my source code for bool checkUnique.
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter; j < TOTAL_NUM; j++)
{
if (j != counter) {
if (combinedArray[counter] == combinedArray[j])
{
return true;
}
}
return false;
}
}
}
I added all elements(TOTAL_NUM = 9) from three different arrays into a new array called combinedArray. When I ran my code and entered 1 2 3 4 5 6 7 8 9, result is still showing that there are duplicates. I tried different methods I found online but still cant get this function to work. Any help would be greatly appreciated
You're quite close to a correct solution, which might look like this:
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter; j < TOTAL_NUM; j++)
{
if (j != counter) {
if (combinedArray[counter] == combinedArray[j])
{
return true;
}
}
}
}
return false;
}
The only change relative to your code is that I moved return false; behind the loops. Why? Because you need to check all pairs before you can assert that there are no duplicates.
This solution might be further improved by changing the starting index of the inner loop:
bool checkUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter + 1; j < TOTAL_NUM; j++)
{
if (combinedArray[counter] == combinedArray[j])
return true;
}
}
return false;
}
Here I changed the initializer of the inner loop into int j = counter + 1 so that I'm sure that j will never be equal to counter.
In this solution you need to make up to 36 comparisons. Alternative approaches:
sort combinedArray and check via std::unique whether it contains duplicates.
insert the elements into std::set and check if its size is 9
Since your array is small, these more universal solutions may be not optimal, you'd need to make tests.
Finally a side remark: try to use consistent names to your variables. counter looks very different from j, which suggests that there's a fundamental difference between the two loop control variables. But there's none: they're very similar to each other. So give them similar names. In the same spirit, please use more useful function names. For example, I'd prefer allUnique that would return true if and only if all input umbers are unique. Compare if (checkUnique(a, b, c, 9)) with if (allUnique(a, b, c, 9)). Of course this, in fact, should be called if allUnique(a, b, c, 3), because the information about array lengths is more fundamental than about the effective buffer length.
EDIT
Actually, you have not defined precisely what the expected output of your function is. If you assume that checkUnique should return true if all numbers are different, then rename it to something more significant and swap all true and false:
bool allUnique(int arrayRow1[], int arrayRow2[], int arrayRow3[], int TOTAL_NUM)
{
int combinedArray[] = { arrayRow1[0], arrayRow1[1], arrayRow1[2],
arrayRow2[0], arrayRow2[1], arrayRow3[2],
arrayRow3[0], arrayRow3[1], arrayRow3[2] };
for (int counter = 0; counter < TOTAL_NUM; counter++)
{
for (int j = counter + 1; j < TOTAL_NUM; j++)
{
if (combinedArray[counter] == combinedArray[j])
return false;
}
}
return true;
}

Return the smallest positive integer that does not occur in an array A of N integers using Function- int solution(vector<int> &A);

Write a function:
int solution(vector<int> &A);
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [-1, -3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [-1,000,000..1,000,000].
My solution below had 100% correctness but performance was only 25%.
What can I do to improve my performance rating?
int solution(vector<int> &A) {
int s=A.size();
int x = 1;
bool neg=true;
for (int i=0; i<s;i++){ //check if all integers are negative
if (A[i]>0){
neg = false;
goto check;
}
}
check:
if (neg==true){
return x; //returns 1 if all integers are negative
}
for (int i=0; i<s; i++){
for(int j=0; j<s; j++){
if (A[j] == x ){
x=A[j]+1;
break;
}
}
}
return x;
}
this is my codility score.
As mentioned in the comments your approach takes O(n^2) time.
To get faster results you need a better algorithm.
One thing mentioned was sorting the vector. Throw away everything <= 0 at the same time and then you can just go through the resulting vector and check for the first hole. That gets you down to O(n log n) time.
The other algorithm mentioned was to use an unordered set or vector<bool> and mark all the numbers present and then find the first one not present. Note that the answer must be a number between 1 and n + 1 for an input of n numbers. So you can greatly reduce the size of the unordered set or vector you need. At most 12.5kb of memory.
FWIW, my solution below scored 100% on codility in all sections. Idea is to maintain a candidate as we punch out possible candidates from a second array. It's in C btw.
int solution(int A[], int N) {
int i, j, rv;
rv = 1;;
int arr[10000002] = {0};
for (i = 0; i < N; i++) {
if (A[i] < 1)
continue;
if (arr[A[i]] == 0)
arr[A[i]] = 1;
if (A[i] == rv) {
for (j = rv + 1; j < 10000002; j++) {
if (arr[j] == 0) {
rv = j;
break;
}
}
}
}
return rv;
}

How do I memoize this recurrence relation?

I am solving Maximum Subarray Sum with One Deletion on LeetCode:
Given an array of integers, return the maximum sum for a non-empty subarray (contiguous elements) with at most one element deletion. For input arr = [1,-2,0,3], output should be 4.
I came up with a recursive solution as below:
class Solution {
public:
int helper(vector<int>& n, vector<int>& cache, int startIndex) {
if(startIndex>=n.size()) return INT_MIN;
if(cache[startIndex]!=-1) return cache[startIndex];
int allInclusiveSum=0, sumWithOneDel=0, lowestVal=INT_MAX, maxVal=INT_MIN;
for(int i=startIndex; i<n.size(); i++) {
allInclusiveSum+=n[i];
maxVal=max(maxVal, allInclusiveSum);
if(i!=startIndex) {
lowestVal=min(lowestVal, n[i]);
sumWithOneDel=allInclusiveSum-lowestVal;
maxVal=max(maxVal, sumWithOneDel);
}
}
maxVal=max(maxVal, helper(n, cache, startIndex+1));
return cache[startIndex]=maxVal;
}
int maximumSum(vector<int>& arr) {
int i=0, first=arr[0];
for(i=1; i<arr.size(); i++)
if(arr[i]!=first) break;
if(i==arr.size()) return first;
vector<int> cache(arr.size(), -1);
return helper(arr, cache, 0);
}
};
Unfortunately, this TLEs. Since I call recursively with startIndex+1, I don't really think I am encountering overlapping sub-problems.
Is there a way I could memoize my solution? If no, why?
With dynamic programming, we would just define a std::vector with N rows and two columns, then run through our arr in one pass, and use std::max to find max_sum:
#include <vector>
#include <algorithm>
class Solution {
public:
static inline int maximumSum(const std::vector<int> &arr) {
int length = arr.size();
std::vector<std::vector<int>> dynamic_sums(length, std::vector<int>(2, 0));
dynamic_sums[0][0] = arr[0];
int max_sum = arr[0];
for (unsigned int row = 1; row < length; row++) {
dynamic_sums[row][0] = std::max(arr[row], dynamic_sums[row - 1][0] + arr[row]);
dynamic_sums[row][1] = std::max(arr[row], std::max(dynamic_sums[row - 1][1] + arr[row], dynamic_sums[row - 1][0]));
max_sum = std::max(max_sum, std::max(dynamic_sums[row][0], dynamic_sums[row][1]));
}
return max_sum;
}
};
It's similarly O(N) time and O(N) memory.
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.

How to sort an array in C++ in a specific way

I want somehow sort an array, so that it looks like -
a[0]>=a[1]<=a[2]>=a[3]<=a[4]
I don't know where to start.
Any suggestion would be appreciated!
Sort the entire array (Choose any sort algorithm you wish to). Then take each pair from the beginning and swap the elements in the pair
2,4,1,5,6,3,7,9,8,10
Sorted to : 1,2,3,4,5,6,7,8,9,10
Pair and swap : (2,1),(4,3),(6,5),(8,7),(10,9)
result : 2,1,4,3,6,5,8,7,10,9
Here's the code, obviously you can alter the array length and numbers to meet your specifications.
#include <iostream>
#include <algorithm>
using namespace std;
void special_Sort(int *array, int size){
//doesn't return a value, changes the values inside the array
int temp;
//for swapping purposes
sort(array, array+size);
//sorts the array in ascending order
for(int i=0; i<size; i=i+2){
temp=array[i];
array[i]=array[i+1];
array[i+1]=temp;
}
//array is now sorted
}
int main(){
// array declaration, call the function, etc...
int array[10]={2,4,1,5,6,3,7,9,8,10};
int *pointer;
pointer=&array[0];
special_Sort(pointer, 10);
// if you want to print the result
// for(int i =0; i<10; i++)
// cout<<array[i]<<" ";
return 0;
}
I'm assuming here that the relations are inclusive (in the sense that they continue to the end of the line - a[0]>=max(a[1],a[2],...), and a[1]<=min(a[2],a[3],..) and so on). Otherwise this isn't uniquely defined, as {5,4,3,2,1} can get sorted for example into {5,1,4,3,2} or {3,2,5,1,4}.
So, assuming this is the case, it's easily solved by sorting the entire array in descending order, then just interleave them -
a[0], a[n-1], a[1], a[n-2], ...
and so on. Just loop with two indices, one starting from the beginning and one from the end, or use something like this -
for (i=0; i<n/2; i++) {
result[i*2] = sorted[i];
result[i*2+1] = sorted[n-i];
}
if (n%2)
result[n-1] = sorted[n/2]
If you are only sorting it in a way that you want values to rise and fall arbitrarily, you can achieve this by checking values in your array and swapping elements if they do not satisfy the constraints of your sort.
Don't have a compiler on me at the moment and you'd have to implement the swap but something like this could work:
for(i=0; i < a.length(); i++){
//If index is even
if(i%2 == 0){
if(a[i] < a[i+1]){
swap(a[i], a[i+1]);
}
} else { ///If index is odd
if(a[i]>a[i+1]){
swap(a[i], a[i+1];
}
}
}
I don't disagree with the other answers posted here so you will have to find what you need depending on the relation of the even and odd indexed elements.
Steps taken:
1) generate some random array
2) sort array
3) switch elements as needed with alternate <=, >= comparisons
Here's the code that does that: (disregard the random generator, its just an easy way to generate an array)
#define sizeArr 50
int main(void)
{
int array[sizeArr];
int i, temp;
for(i=0;i<sizeArr;i++)
{
array[i]=randomGenerator(1, 1000);
Sleep(2);//force clock tick for new srand() to be effective in rand() generator
}
//sort array
qsort(array, sizeArr, sizeof(int), cmpfunc);
//pick the first non repeat 90th percent and print
for(i=0;i<sizeArr-1;i++)
{
if(i%2==0)//alternate between >= && <=
{
if(array[i+1] >= array[i])
{
temp = array[i+1];
array[i+1]=array[i];
array[i]=temp;
}
}
else
{
if(array[i+1] <= array[i])
{
temp = array[i+1];
array[i+1]=array[i];
array[i]=temp;
}
}
}
getchar();
return 0;
}
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
srand(clock());
while(trying)
{
random = (rand()/32767.0)*(max+1);
(random >= min) ? (trying = 0) : (trying = 1);
}
return random;
}

conditionally testing for equality of vector's elements

Although it seems pretty simple, I'm not sure of the most efficient way of doing this.
I have two vectors:
std::vector<bool> a;
std::vector<int> b;
a.size() necessarily equals b.size().
each bool in a corresponds to an int in b. I want to create a function:
bool test(std::vector<bool> a, std::vector<int> b);
This function returns true if the values in a are equal. However, it only considers values in a that correspond to true values in b.
I could do this:
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned int i;
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
x = a.at(i);
break;
}
}
for(i = 0; i < a.size(); ++i){
if(b.at(i) == true){
if(a.at(i) != x){
return false;
}
}
}
return true;
}
But then I have to create two loops. Although the first loop will stop at the first true value, is there a better way?
Your solution looks good enough to me:
Each loop does a different thing anyway (so you shouldn't worry about duplication)
You don't use extranious variables or flags that complicate the code.
The only problems I see are:
You start the second loop at 0 instead of where you left off.
Doing if(condition == true) is very ugly. Just do if(condition) instead.
bool test(std::vector<int> a, std::vector<bool> b){
int x;
unsigned i;
for(i = 0; i < a.size(); i++){
if(b.at(i)){
x = a.at(i);
break;
}
}
for(i++; i < a.size(); i++){
if(b.at(i)){
if(a.at(i) != x){
return false;
}
}
return true;
}
You can do it in one loop if you remember if you have seen the first true element in b or not. Also, you should take the a and b parameters by reference to avoid unnecessary copying. And finally, if you know that the indices into a vector are always within valid range (i.e. between 0 and vector.size() - 1, inclusive), you can use operator[] instead of at, and achieve better peformance (at does a range check, while operator[] does not). Heres a modified version of your test function considering all the above points:
bool test(std::vector<int> const& a, std::vector<bool> const& b){
int x;
bool first = true;
for(unsigned i = 0, n = a.size(); i != n; ++i){
if( b[i] ){
if( first ) {
x = a[i];
first = false;
}
else if( x != a[i] ) {
return false;
}
}
}
return true;
}
Provided you know a.size() == b.size() just create a single loop that compares an 'a' element to a 'b' element at the same time at each iteration. Once you see that a[i] != b[i] then you know the containers don't match and you can break out.
I am not 100% certain I know what you want to do but a straight compare once you know you have equal size
std::equal(a.begin(), a.end(), b.begin(), std::equal_to<bool>())