Need help in implementing a binary search in C - c

I am trying to write an iterative search in a C program.
The pseudo-code would look like this for it:
while length of list > 0
look at middle of list
if number found, return true
else if number is too high, only consider
left half of list
else if number is too low, only consider
right half of list
return false
I have already implemented a bubble sort (which I assume works). Here is my code right now. The search is currently linear. I need to somehow change it to a binary search (I would prefer to do it iteratively instead of recursively). I'm completely lost on how I should go about doing this though. Can someone please help me?:
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include "helpers.h"
/*
* Returns true if value is in array of n values, else false.
*/
bool
search(int value, int array[], int n)
{
// TODO: re-implement as binary search
int min = 0;
int max = n;
int i;
i=(min+max)/2;
if(array[i] == value)
{
return true;
}
else if(min>=max)
{
return 1;
}
else if(array[i] > value)
{
max = i-1;
}
else if(array[i] < value)
{
min = i+1;
}
return false;
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
//set smade to false to start
//declares the_end as n-1
bool smade = false;
int the_end = n-1;
// TODO: implement an O(n^2) sort
while(the_end > 0)
{
for(int i = 0; i < the_end; i++)
{
int temp;
if (values[i] > values[i+1])
{
temp = values[i];
values[i] = values[i+1];
values[i+1] = temp;
smade=true;
}
}
if(! smade)
{
break;
}
the_end--;
}
return;
}

You just translate your pseudo-code into code. I'll give you some more refined pseudo-code:
1) Set minimum possible location for thing we're looking for (min) to zero.
2) Set maximum possible location for thing we're looking for (max) to the highest-possible location.
3) Compute a location loc as (min+max)/2.
4) Check if loc holds the object we're looking for. If so, stop, we found it.
5) Check if min>=max. If so, stop, it's not here.
5) If the object at loc is too high, set max to loc-1. (Because the maximum location at which it could be is one less than loc, since loc is too high.)
6) If the object at loc is too low, set min to loc+1. (Same logic, the other way around.)
7) Go to step 3.

Soln;
unsigned char search(int value, int array[], int n)
{
int start = 0;
int end = n;
int mid;
// We ll exit the while loop if we just started overlapping
while(start<=end)
{
// Calculating the new mid point
// Can also be written as mid = (start + end)/2;
mid = start + (end-start)/2;
if(value == array[mid])
return 1;
// If value is less we search on the left side
if(value < array[mid])
end = mid - 1;
else
start = mid + 1;
}
return 0;
}

You have the algorithm there. Just start with two index values -- low and high. Set them initially to the first and last entries in the array.
Next pick an (integer) value midway between high and low. Probe that array element. If it's equal to the desired value, you're done. If it's below/smaller/earlier than the desired value then set "low" to the probe element index +1. If it's above/larger/later than the desired value, set "high" to the probe element index -1. Then go back (in your while loop) and pick a new "midway" value.
If you get to where low > high (check in the while condition) then the value is not found.
(I'll add that the algorithm is basically simple, but can be frustratingly buggy if you don't think it out well and try to take some shortcuts.)

Related

This version of selection sort I tried to make doesnot work properly, but it works surprisingly for larger arrays

I was doing selection sort yesterday. I wondered if I could replace the min and max values to begining and end of the unsorted array every time I iterated. I am just a beginner at programming, so its obvious that this wouldn't work. However, suprisingly, the code below does sort a larger array (~ 30k - 40k) in size. I experimented by generating random values from rand()%2000 and the function sorted the array successfully 28 times in 30 experiments.
But it can't sort something as simple as {4,2,3}
I think there's a bug somewhere, I couldn't figure it out so I've come here.
I'm also curious about the fact that it sorted such large arrays successfully. How?
int *zigzag_sort(int arr[])
{
// loop through array
// find min and max
// replace min at begining and max at end
// keep doing until sorted
int f_idx = 0, l_idx = n-1;
int min_pos, max_pos;
while( f_idx < l_idx ) {
min_pos = f_idx;
max_pos = l_idx;
for(int i = f_idx+1; i <= l_idx; i++)
{
if(arr[i] < arr[min_pos])
min_pos = i;
else if(arr[i] > arr[max_pos])
max_pos = i;
}
swap(&arr[f_idx], &arr[min_pos]);
swap(&arr[l_idx], &arr[max_pos]);
f_idx++;
l_idx--;
}
return arr;
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
Your swaps are not as simple as you think, and there is a hole in your position starting points going in to the inner loop iterations.
First, there are there situations that must be accounted after completing a segment enumeration and finding the segment min-index and max-index locations. They all deal with where you're reading data from, and where you'r'e trying to write it to. There can be partial, or in one case, full, overlap.
After each inner iteration, one of several conditions can transpire...
(min_pos == l_idx) && (max_pos == f_idx) . In other words, the minimum and maximum values are each in the places where the other wants to be. If that is the case ONE swap is needed (each other) and you're done for that iteration.
One of (min_pos == l_idx) or (max_pos == f_idx) is true, but not both. The order of the impending two swaps is important, depending on which of those conditions is true. In short, don't swap something into a slot that is about to be swapped again with the second swap. Ex: If the maximum value resides at the low target position, you need to swap it out to the maximum target position before the minimum value is swapped to the low target position. Otherwise you will dislocate something right after you put it home.
Neither of the above are true, in which case two swaps are still required, but order is irrelevant.
The probability of the special cases in (1) and (2) above increase significantly as you squeeze the iteration window down further and further during the outer loop iteration. For a random ordering, sooner or later it is going to happen.
Secondly, both the min_pos and max_pos starting points should be the same location in the segment, f_idx. It may not seem important, but it is so because the inner loop starts a f_idx+1. that means if the maximum value of the iteration was originally at f_idx you never accounted for it, will not discover it, etc.
The fixed routine is below, with notes where appropriate.
int *zigzag_sort(int arr[], int n)
{
int f_idx = 0, l_idx = n - 1;
while (f_idx < l_idx)
{
// both should start at the same location
int min_pos = f_idx;
int max_pos = f_idx;
for (int i = f_idx + 1; i <= l_idx; i++)
{
if (arr[i] < arr[min_pos])
min_pos = i;
else if (arr[i] > arr[max_pos])
max_pos = i;
}
if (max_pos == f_idx)
{
if (min_pos == l_idx)
{
// swap each other
swap(&arr[max_pos], &arr[min_pos]);
}
else
{ // swap the max out before overwritine with min
swap(&arr[l_idx], &arr[max_pos]);
swap(&arr[f_idx], &arr[min_pos]);
}
}
else
{ // also handle the case of l_idx == min_pos
swap(&arr[f_idx], &arr[min_pos]);
swap(&arr[l_idx], &arr[max_pos]);
}
f_idx++;
l_idx--;
}
return arr;
}
Why doesn't it work for { 4, 2, 3 }?
... // f_idx = 0; l_idx = 2; min_pos = 1; max_pos = 0;
swap(&arr[f_idx], &arr[min_pos]); // swap(&arr[0], &arr[1]) ==> { 2, 4, 3 }
// ===> max_pos is "wrong" now <===
swap(&arr[l_idx], &arr[max_pos]); // swap(&arr[2], &arr[0]) ==> { 3, 4, 2 }

Same Binary search not working, one circumstance, but working in another

Going through CS50, Pset3 and desperate for help/patience.
I'm trying to implemented helpers.c so that find.c has the correct functions to call.. However it is not connecting..
I did a separate piece I titled testBinSearch and that did work. With the same code.. can someone tell me why..?
/**
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
*/
#include <stdio.h>
#include <cs50.h>
#include "helpers.h"
/**
* Returns true if value is in array of n values, else false.
*/
//search(needle, haystack, size)
bool search(int value, int values[], int n)
{
// TODO: implement a Binary searching algorithm (You are welcome to take an iterative approach (as with a loop) or a recursive approach (wherein a function calls itself).)
//define startPoint. numberOfArrayElements(aka size) - (numberOfArrayElements(aka size) - 1) or Element[0]
//define endPoint. numberOfArrayElements(aka size)
int endPoint = n - 1; //element! we -1 because array start from 0th element. last element of array that is 5 elements big will thus be (total number of Elements - 1)th element.
//define midPoint. numberOfArrayElements(aka size)/2
int midPoint = endPoint/2; //element!
//while loop?
while(n > 0)
{
//if midPoint == needle, return 0
if(values[midPoint] == value)
{
return 0;
}
//////////(if midPoint is smaller(to the left) or larger(to the right) than needle)
//ELSE IF midPoint > than needle(look left), keep startPoint, change endPoint element to values[midPoint - 1], define midPoint again.
else if(values[midPoint] > value)
{
endPoint = midPoint - 1;
midPoint = endPoint/2;
n = endPoint;
printf("mid point is more than needle\n");
}
//ELSE midPoint < than needle(look right), keep endPoint, change Startpoint element to values[midPoint + 1], define mindPoint again.
else if(values[midPoint] < value)
{
int startPoint = midPoint + 1;
//define midpoint again
midPoint = (endPoint + startPoint)/2;
n = endPoint - startPoint + 1;
printf("mid point is less than needle\n");
}
}
printf("cued the while loop return 1\n");
return 1;
}
/**
* Sorts array of n values. Done with Insertion sort*
*/
void sort(int values[], int n)
{
//declare variable
int element;
//number of iterations (or passes?). Skip first because first array is already sorted
for (int i = 1; i < n; i++)
{
//value of element moving into sorted portion
element = values[i];
//declare variable
int j = 0;
//index into the unsorted portion
j = i;
//iterate sorted portion from right to left while sorted portion is greater than 'Element' being compared in this iteration of i.
//basically, it stops this loop once the 'Element' is placed to the left of all greater&&sorted numbers.
while(j > 0 && values[j - 1] > element)
{
//shift all sorted positions to the right
values[j] = values[j - 1];
// this enables the loop to move left through the sorted portion
j = j - 1;
}
//insert temp holder value into the position which is now empty because all sorted&&greater number are to the right of 'Element'
values[j] = element;
}
for(int k = 0; k < n; k++)
//print to check
{
printf("{%i}<-- number in %i-th array (sorted)\n", values[k], k);
}
}
Here is the find.c code:
/**
* find.c
*
* Computer Science 50
* Problem Set 3
*
* Prompts user for as many as MAX values until EOF is reached,
* then proceeds to search that "haystack" of values for given needle.
*
* Usage: ./find needle
*
* where needle is the value to find in a haystack of values
*/
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include "helpers.h"
// maximum amount of hay
const int MAX = 65536;
int main(int argc, string argv[])
{
// ensure proper usage
if (argc != 2)
{
printf("Usage: ./find needle\n");
return -1;
}
// remember needle
int needle = atoi(argv[1]);
// fill haystack
int size;
int haystack[MAX];
for (size = 0; size < MAX; size++)
{
// wait for hay until EOF
printf("\nhaystack[%i] = ", size);
int straw = GetInt();
if (straw == INT_MAX)
{
break;
}
// add hay to stack
haystack[size] = straw;
}
printf("\n");
// sort the haystack
sort(haystack, size);
// try to find needle in haystack
if (search(needle, haystack, size))
{
printf("\nFound needle in haystack!\n\n");
return 0;
}
else
{
printf("\nDidn't find needle in haystack.\n\n");
return 1;
}
}
And finally, here's the code that worked(or at least it seems to work) separately when I keyed them all in one file... titled testBinSearch below
#include <stdio.h>
#include <cs50.h>
void sort(int array[], int NumberOfElements);
bool search(int value, int values[], int n);
int main(void)
{
//decalre variable
int NumberOfElements;
printf("how many Element would you like in this array?\n");
NumberOfElements = GetInt();
//declare variable for array
int array[NumberOfElements];
for(int i = 0; i < NumberOfElements; i++)
{
printf("alright, please key in value of each element\n");
array[i] = GetInt();
}
sort(array, NumberOfElements);
for (int i = 0; i < NumberOfElements; i++)
{
printf("alright, here is your array sorted, element %i is %i\n", i, array[i]);
}
printf("value ot search for?\n");
int value = GetInt();
search(value, array, NumberOfElements);
}
//----------
void sort(int array[], int NumberOfElements)
{
//declare variable
int element;
//number of iterations (or passes?). Skip first because first array is already sorted
for (int i = 1; i < NumberOfElements; i++)
{
//value of element moving into sorted portion
element = array[i];
//declare variable
int j = 0;
//index into the unsorted portion
j = i;
//iterate sorted portion from right to left while sorted portion is greater than 'Element' being compared in this iteration of i.
//basically, it stops this loop once the 'Element' is placed to the left of all greater&&sorted numbers.
while(j > 0 && array[j - 1] > element)
{
//shift all sorted positions to the right
array[j] = array [j - 1];
// this enables the loop to move left through the sorted portion
j = j - 1;
}
//insert temp holder value into the position which is now empty because all sorted&&greater number are to the right of 'Element'
array[j] = element;
}
}
//--------------
bool search(int value, int values[], int n)
{
// TODO: implement a Binary searching algorithm (You are welcome to take an iterative approach (as with a loop) or a recursive approach (wherein a function calls itself).)
//variables declaration
//int startPoint;
//int endPoint;
//int midPoint;
//define startPoint. numberOfArrayElements(aka size) - (numberOfArrayElements(aka size) - 1) or Element[0]
//define endPoint. numberOfArrayElements(aka size)
int endPoint = n - 1; //element!
//define midPoint. numberOfArrayElements(aka size)/2
int midPoint = endPoint/2; //element!
//while loop?
while(n > 0)
{
//if midPoint == needle, return 0
if(values[midPoint] == value)
{
printf("found it!\n");
return 0;
}
//////////(if midPoint is smaller(to the left) or larger(to the right) than needle)
//ELSE IF midPoint > than needle(look left), keep startPoint, change endPoint element to values[midPoint - 1], define midPoint again.
else if(values[midPoint] > value)
{
endPoint = midPoint - 1;
midPoint = endPoint/2;
n = endPoint;
}
//ELSE midPoint < than needle(look right), keep endPoint, change Startpoint element to values[midPoint + 1], define mindPoint again.
else if(values[midPoint] < value)
{
int startPoint = midPoint + 1;
//define midpoint again
midPoint = (endPoint + startPoint)/2;
n = endPoint - startPoint + 1;
}
}
printf("could not find it\n");
return 1;
}
Can someone help me out and tell me where I went wrong? I came up with the code and copied it right over, but one worked(testBinSearch) and one didn't(helpers.c).. ?
I'm not sure if this covers the whole problem but anyway...
This calculation
midPoint = endPoint/2;
is wrong.
Assume you have an array of 100 elements. The code may bring you to a situation where you look at index 75 to 99 with midpoint in between (e.g. 87), i.e. you have taken the smaller than path a couple of times.
Now if you take the greater than part you calculate a midpoint (e.g. 43) being outside the range of interest
Further, the startpoint variable is not to be a variable inside the smaller than case. It must be at the same level as endpoint. In each loop you must change either startpoint or endpoint. Calculation of midpoint shall always depend on both startpoint and endpoint.

How can I simplify this working Binary Search code in C?

Hey guys started programming in C few weeks ago learning about algothiritms, just wondering how would you make my code more simple its just a binary search function. But the only thing is you must keep the arguments the same, thanks in advance.
bool search(int value, int values[], int n)
{
int min = values[0];
int max = values[n-1];
int average = (min + max) / 2;
if(average == value)
{
return true;
}
while (average > value)
{
max = average - 1;
average = (min + max) / 2;
}
while (average < value)
{
min = average + 1;
average = (min + max) / 2;
}
if (max < min)
{
return false;
}
if (average == value) {
printf("%i\n", average);
return true;
}
else
{
return false;
}
}
There are a bunch of little things you have to get right in a binary search: handle the length=0 case, make sure the position you test is always valid, make sure you don't overflow (i.e., `(low+high)/2' is not the best way to write that), make sure the new test position is always different from the previous one, etc.
After having done it like a million times, every binary search I write is now done just like this:
bool search(int[] array, int length, int valueToFind)
{
int pos=0;
int limit=length;
while(pos<limit)
{
int testpos = pos+((limit-pos)>>1);
if (array[testpos]<valueToFind)
pos=testpos+1;
else
limit=testpos;
}
return (pos < length && array[pos]==valueToFind);
}
Notice that we only need to do one comparison per iteration, which is faster than most implementations that can do 2. Instead of doing the equality test inside the loop, we reliably find the position where the element to find belongs, using only one comparison per iteration, and then at the end test to see if the element we want is there.
The way we calculate testpos ensures that pos <= testpos < limit, AND it works even if length is the largest possible integer value.
This form also makes it very easy to read off the invariants you want to see, without having to think about strange boundary conditions like high<low. When you come out of the loop, pos==limit so you don't have to worry about using the wrong one, etc.
The condition in this loop is also easily adaptable to different-purpose binary searches like "find where to insert x, ensuring that it goes after all the xs that are already in the array", "find the first x in the array", "find the last x in the array", etc.
This is not a right implementation of binary search ,all conditions must be in one loop ,such as:
Also max must be n-1 and not values[n-1] and min=0 instead of values[0] as also you should compare values[average] with value not just average variable.
bool search(int value, int values[], int n){
int min = 0;
int max = n-1;
int average ;
while(max>=min){
average = (min + max) / 2;
if(values[average] == value)
{
return true;
}
if (values[average] > value)
{
max = average - 1;
average = (min + max) / 2;
}
if (values[average] < value)
{
min = average + 1;
average = (min + max) / 2;
}
}
return false;
}

Find max difference in array element

Sample case:
a[]={1,4,2,5,10,5,4}; //output== 9
here we cannot change the order of element smaller always appear before bigger element
The constraint are:
1<=n<=10^4
10^-6<=a[i]<=10^-6
Here is my code but it will fail on some test cases ,can someone find the error in this code.
Thank You .
int maxDiff(int *a,int n)
{
int MIN_value=INT_MAX;
int MAX_vale=INT_MIN;
for(int i=0;i<n;i++) {
MIN_value=min(MIN_value,a[i]);
MAX_value=max(a[i]-MIN_value,MAX_value);
}
return MAX_value;
}
Your function is wrong because, if it finds the minimum value at the end of the array, all your previous calculations of differences are invalidated. Your error is thus in the line:
MAX_value=max(a[i]-MIN_value,MAX_value);
A much better way to go about this would be:
int maxDiff(int *a,int n)
{
if (n == 0 || n == 1) //If list is empty or has 1 element, return 0
return 0;
int MIN_value=INT_MAX;
int MAX_vale=INT_MIN;
for(int i=0;i<n;i++) {
MIN_value=min(MIN_value,a[i]);
MAX_value=max(a[i],MAX_value);
}
return MAX_value - MIN_VALUE;
}
The error must be in the logic of this line:
MAX_value=max(a[i]-MIN_value,MAX_value);
Use a debugger to test the method on different inputs and trace if MAX_Value gets the values assigned you expect it to get.
You may just set MAX_value correctly and return the difference afterwards:
MAX_value=max(MAX_value,a[i]);
Finally:
return MAX_VALUE - MIN_VALUE;
Be aware that if the difference is negative then the array was empty.
Edit: Compute the difference between the maximal value and the minimal value to the left of the maximal value (see comments):
possibleMinValue = min(possibleMinValue,a[i]);
oldMaxValue = MAX_value;
MAX_value=max(MAX_value,a[i]);
if (oldMaxValue != MAX_value) {
// Found a new maximal value. Thus, possibleMinValue is a valid min value
MIN_value = possibleMinValue;
}
When finding the min or max of an array it is best to set the initial max or min to the first possible outcome; in this case it would be number 1 - number 2. This is to ensure that INT_MAX and INT_MIN do not become your final answer. Alternatively, when finding the min you can use INT_MAX as the initial value for your min or vice versa.
int findMaxDiff(int* array, int n) {
int max = array[i];
int min = array[i];
for(int i = 0; i < n; i++) {
if(array[i] > max) {
max = array[i]
}
if(array[i] < min) {
min = array[i]
}
}
return max - min;
}

Find the majority element in array

The majority element is the element that occurs more than half of the size of the array.
How to find the majority element in an array in O(n)?
Example input:
{2,1,2,3,4,2,1,2,2}
Expected output:
2
// returns -1 if there is no element that is the majority element, otherwise that element
// funda :: if there is a majority element in an array, say x, then it is okay to discard
// a part of that array that has no majority element, the remaining array will still have
// x as the majority element
// worst case complexity : O(n)
int findMajorityElement(int* arr, int size) {
int count = 0, i, majorityElement;
for (i = 0; i < size; i++) {
if (count == 0)
majorityElement = arr[i];
if (arr[i] == majorityElement)
count++;
else
count--;
}
count = 0;
for (i = 0; i < size; i++)
if (arr[i] == majorityElement)
count++;
if (count > size/2)
return majorityElement;
return -1;
}
It is sad to see that in 5 years no one has written a proper explanation for this problem.
This is a standard problem in streaming algorithms (where you have a huge (potentially infinite) stream of data) and you have to calculate some statistics from this stream, passing through this stream once.
Clearly you can approach it with hashing or sorting, but with a potentially infinite stream you can clearly run out of memory. So you have to do something smart here.
The majority element is the element that occurs more than half of the size of the array. This means that the majority element occurs more than all the other elements combined. That is, if you count the number of times the majority element appears, and subtract the number of occurrences of all the other elements, you will get a positive number.
So if you count the occurrences of some element, and subtract the number of occurrences of all other elements and get the number 0 - then your original element can't be a majority element. This is the basis for a correct algorithm:
Declare two variables, counter and possible_element. Iterate the stream, if the counter is 0 - your overwrite the possible element and initialize the counter, if the number is the same as possible element - increase the counter, otherwise decrease it. Python code:
def majority_element(arr):
counter, possible_element = 0, None
for i in arr:
if counter == 0:
possible_element, counter = i, 1
elif i == possible_element:
counter += 1
else:
counter -= 1
return possible_element
It is clear to see that the algorithm is O(n) with a very small constant before O(n) (like 3). Also it looks like the space complexity is O(1), because we have only three variable initialized. The problem is that one of these variables is a counter which potentially can grow up to n (when the array consists of the same numbers). And to store the number n you need O(log (n)) space. So from theoretical point of view it is O(n) time and O(log(n)) space. From practical, you can fit 2^128 number in a longint and this number of elements in the array is unimaginably huge.
Also note that the algorithm works only if there is a majority element. If such element does not exist it will still return some number, which will surely be wrong. (it is easy to modify the algorithm to tell whether the majority element exists)
History channel: this algorithm was invented somewhere in 1982 by Boyer, Moore and called Boyer–Moore majority vote algorithm
The majority element (if it exists) will also be the median. We can find the median in O(n) and then check that it is indeed a valid majority element in O(n).
More details for implementation link
Majority Element:
A majority element in an array A[] of size n is an element that appears more than n/2 times (and hence there is at most one such element).
Finding a Candidate:
The algorithm for first phase that works in O(n) is known as Moore’s Voting Algorithm. Basic idea of the algorithm is if we cancel out each occurrence of an element e with all the other elements that are different from e then e will exist till end if it is a majority element.
findCandidate(a[], size)
1. Initialize index and count of majority element
maj_index = 0, count = 1
2. Loop for i = 1 to size – 1
(a)If a[maj_index] == a[i]
count++
(b)Else
count--;
(c)If count == 0
maj_index = i;
count = 1
3. Return a[maj_index]
Above algorithm loops through each element and maintains a count of a[maj_index], If next element is same then increments the count, if next element is not same then decrements the count, and if the count reaches 0 then changes the maj_index to the current element and sets count to 1.
First Phase algorithm gives us a candidate element. In second phase we need to check if the candidate is really a majority element.
Second phase is simple and can be easily done in O(n). We just need to check if count of the candidate element is greater than n/2.
Read geeksforgeeks for more details
Time:O(n)
Space:O(n)
Walk the tree and count the occurrence of elements in a hash table.
Time:O(n lg n) or O(n*m)(depends on the sort used)
space:(1)
sort the array then count occurrences of the elements.
The interview correct answer: Moore’s Voting Algorithm
Time: O(n)
Space:O(1)
Walk the list compare the current number vs current best guess number. If the number is equal to the current best guess number increment a counter, otherwise decrement the counter and if the counter hits zero replace the current best guess number with the current number and set the counter to 1. When you get to the end the current best guess is the Candidate number, walk the list again just counting instances of the candidate. If the final count is greater than n/2 then it is the majority number otherwise there isn't one.
How about a random sampling approach? You could sample, say sqrt(n) elements and for each element that occurred more than sqrt(n) / 4 times (can be accomplished naively in O(n) time and O(sqrt(n)) space), you could check whether it was a majority element in O(n) time.
This method finds the majority with high probability because the majority element would be sampled at least sqrt(n) / 2 times in expectation, with a standard deviation of at most n^{1/4} / 2.
Another sampling approach that is similar to an approach I saw in one of the duplicate links is to draw two samples, and if they are equal verify that you have found the majority element in O(n) time. The additional verification step is necessary because the other elements besides the majority may not be distinct.
In Monte-Carlo algorithm,
Majority (a,n)
//a[]-array of 'n' natural numbers
{
j=random(0,1,....,n-1)
/*Selecting the integers at random ranging from 0 to n-1*/
b=a[j];c=0;
for k from 0 to n-1 do
{
if a[k]=b then,
c=c+1;
}
return (c>n/2)
}
public class MajorityElement
{
public static void main(String[] args)
{
int arr[]={3,4,3,5,3,90,3,3};
for(int i=0;i<arr.length;i++)
{
int count=0;
int j=0;
while(j<arr.length-1)
{
if(i==j)
j=j+1;
if(arr[i]==arr[j])
count++;
j++;
}
if(count>=arr.length/2)
{
System.out.println("majority element"+arr[i]);
break;
}
}
}
}
To find the majority of an element in an array then you can use Moore's Majority Vote Algorithm which is one of best algorithm for it.
Time Complexity: O(n) or linear time
Space Complexity: O(1) or constant space
Read more at Moore's Majority Vote Algorithm and GeeksforGeeks
If you are allowed to create a hash-table and assume hash-entry lookup is constant you just hash_map each entry against the number of occurrences.
You could do a second pass through the table you get the one with the highest count, but if you know in advance the number of elements in the table, you will know immediately if we have a majority element on the first pass when we hit the required count on the element.
You cannot guarantee of course that there is even a sequence of 2 consecutive occurrences of the element eg 1010101010101010101 has no consecutive 1s but it is a majority element.
We are not told anything about whether there is any kind of ordering on the element type although obviously we must be able to compare two for equality.
int majorityElement(int[] num) {
int major=num[0], count = 1;
for(int i=1; i<num.length;i++){
if(count==0){
count++;
major=num[i];
}
else if(major==num[i]){
count++;
}
else
count--;
}
return major;
}
Time Complexity O(n)
A modified version Boyer's Algorithm,
3 passes where,
In the first pass, we do a forward iteration of the array
In the second pass, we do a reverse iteration of the array.
In third pass, get counts for both the majority elements obtained in first and second passes.
Technically a linear complexity algorithm (O(3n)).
I believe this should work for an array with a majority element that occurs at least n/2 times.
#include <iostream>
#include <vector>
template <typename DataType>
DataType FindMajorityElement(std::vector<DataType> arr) {
// Modified BOYERS ALGORITHM with forward and reverse passes
// Count will stay positive if there is a majority element
auto GetMajority = [](auto seq_begin, auto seq_end) -> DataType{
int count = 1;
DataType majority = *(seq_begin);
for (auto itr = seq_begin+1; itr != seq_end; ++itr) {
count += (*itr == majority) ? 1 : -1;
if (count <= 0) { // Flip the majority and set the count to zero whenever it falls below zero
majority = *(itr);
count = 0;
}
}
return majority;
};
DataType majority1 = GetMajority(arr.begin(), arr.end());
DataType majority2 = GetMajority(arr.rbegin(), arr.rend());
int maj1_count = 0, maj2_count = 0;
// Check if any of the the majority elements is really the majority
for (const auto& itr: arr) {
maj1_count += majority1 == itr ? 1 : 0;
maj2_count += majority2 == itr ? 1 : 0;
}
if (maj1_count >= arr.size()/2)
return majority1;
if (maj2_count >= arr.size()/2)
return majority2;
// else return -1
return -1;
}
Code tested here
Thanks for the previous answers which inspired me to know Bob Boyer's algo. :)
Java generic version: A modified version of Boyer's Algorithm
Note: array of primitive type could use wrapper.
import com.sun.deploy.util.ArrayUtil;
import com.sun.tools.javac.util.ArrayUtils;
/**
* Created by yesimroy on 11/6/16.
*/
public class FindTheMajority {
/**
*
* #param array
* #return the value of the majority elements
*/
public static <E> E findTheMajority(E[] array){
E majority =null;
int count =0;
for(int i=0; i<array.length; i++){
if(count==0){
majority = array[i];
}
if(array[i].equals(majority)){
count++;
}else{
count--;
}
}
count = 0;
for(int i=0; i<array.length ; i++){
if(array[i].equals(majority)){
count++;
}
}
if(count > (array.length /2)){
return majority;
}else{
return null;
}
}
public static void main(String[] args){
String[] test_case1 = {"Roy","Roy","Roy","Ane","Dan","Dan","Ane","Ane","Ane","Ane","Ane"};
Integer[] test_case2 = {1,3,2,3,3,3,3,4,5};
System.out.println("test_case1_result:" + findTheMajority(test_case1));
System.out.println("test case1 the number of majority element should greater than" + test_case1.length/2);
System.out.println();
System.out.println("test_case2_result:" + findTheMajority(test_case2));
System.out.println("test case2 the number of majority element should greater than" + test_case2.length/2);
System.out.println();
}
}
//Suppose we are given an array A.
//If we have all the elements in the given array such each element is less than K, then we can create an additional array B with length K+1.
//Initialize the value at each index of the array with 0.
//Then iterate through the given array A, for each array value A[i], increment the value with 1 at the corresponding index A[i] in the created array B.
//After iterating through the array A, now iterate through the array B and find the maximum value. If you find the value greater than the n/2 then return that particular index.
//Time Complexity will be O(n+K) if K<=n then equivalent to O(n).
//We have a constraint here that all elements of the array are O(K).
//Assuming that each element is less than or equal to 100, in this case K is 100.
import javax.print.attribute.standard.Finishings;
public class MajorityElement {
private static int maxElement=100;
//Will have all zero values initially
private static int arrB[]=new int[maxElement+1];
static int findMajorityElement(int[] arrA) {
int count = 0, i, majorityElement;
int n=arrA.length;
for (i = 0; i < n; i++) {
arrB[arrA[i]]+=1;
}
int maxElementIndex=1;
for (i = 2; i < arrB.length; i++){
if (arrB[i]>n/2) {
maxElementIndex=i;
break;
}
}
return maxElementIndex;
}`
public static void main(String[] args) {
int arr[]={2,6,3,2,2,3,2,2};
System.out.println(findMajorityElement(arr));
}
}
This will Help you and if two elements repeat same number of times if will show none.
int findCandidate(int a[], int size)
{
int count,temp=0,i,j, maj;
for (i = 0; i < size; i++) {
count=0;
for(j=i;j<size;j++)
{
if(a[j]==a[i])
count++;
}
if(count>temp)
{
temp=count;
maj=i;
}
else if(count==temp)
{
maj=-1;
}
}
return maj;
}
This is how I do it in C++ using vector and multimap (JSON with repeat keys).
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <iterator>
using namespace std;
vector <int> majorityTwoElement(vector <int> nums) {
// declare variables
multimap <int, int> nums_map;
vector <int> ret_vec, nums_unique (nums);
int count = 0;
bool debug = false;
try {
// get vector of unique numbers and sort them
sort(nums_unique.begin(), nums_unique.end());
nums_unique.erase(unique(nums_unique.begin(), nums_unique.end()), nums_unique.end());
// create map of numbers and their count
for(size_t i = 0; i < nums_unique.size(); i++){
// get number
int num = nums_unique.at(i);
if (debug) {
cout << "num = " << num << endl;
}
// get count of number
count = 0; // reset count
for(size_t j = 0; j < nums.size(); j++) {
if (num == nums.at(j)) {
count++;
}
}
// insert number and their count into map (sorted in ascending order by default)
if (debug) {
cout << "num = " << num << "; count = " << count << endl;
}
nums_map.insert(pair<int, int> (count, num));
}
// print map
if (debug) {
for (const auto &p : nums_map) {
cout << "nums_map[" << p.first << "] = " << p.second << endl;
}
}
// create return vector
if (!nums_map.empty()) {
// get data
auto it = prev(nums_map.end(), 1);
auto it1 = prev(nums_map.end(), 2);
int last_key = it->first;
int second_last_key = it1->first;
// handle data
if (last_key == second_last_key) { // tie for repeat count
ret_vec.push_back(it->second);
ret_vec.push_back(it1->second);
} else { // no tie
ret_vec.push_back(it->second);
}
}
} catch(const std::exception& e) {
cerr << "e.what() = " << e.what() << endl;
throw -1;
}
return ret_vec;
}
int main() {
vector <int> nums = {2, 1, 2, 3, 4, 2, 1, 2, 2};
try {
// get vector
vector <int> result = majorityTwoElement(nums);
// print vector
for(size_t i = 0; i < result.size(); i++) {
cout << "result.at(" << i << ") = " << result.at(i) << endl;
}
} catch(int error) {
cerr << "error = " << error << endl;
return -1;
}
return 0;
}
// g++ test.cpp
// ./a.out
Use Divide and Conquer to find majority element. If we divide the array in to two halves the majority element should be a majority in one of the halves. If we go ahead and combine the sub arrays we can find out if the majority element is also the majority of the combined array. This has O(nlogN)complexity.
Here is a C++ implementation:
#include <algorithm>
#include <iostream>
#include <vector>
using std::vector;
// return the count of elem in the array
int count(vector <int> &a, int elem, int low, int high)
{
if (elem == -1) {
return -1;
}
int num = 0;
for (int i = low; i <= high; i++) {
if (a[i] == elem) {
num++;
}
}
return num;
}
// return the majority element of combined sub-array. If no majority return -1
int combined(vector <int> &a, int maj1, int maj2, int low, int mid, int high)
{
// if both sub arrays have same majority elem then we can safely say
// the entire array has same majority elem.
// NOTE: No majority ie. -1 will be taken care too
if (maj1 == maj2) {
return maj1;
}
// Conflicting majorities
if (maj1 != maj2) {
// Find the count of each maj1 and maj2 in complete array
int num_maj1 = count(a, maj1, low, high);
int num_maj2 = count(a, maj2, low, high);
if (num_maj1 == num_maj2) {
return -1;
}
int half = (high - low + 1) / 2;
if (num_maj1 > half) {
return maj1;
} else if (num_maj2 > half) {
return maj2;
}
}
return -1;
}
// Divide the array into 2 sub-arrays. If we have a majority element, then it
// should be a majority in at least one of the half. In combine step we will
// check if this majority element is majority of the combination of sub-arrays.
// array a and low is lower index and high is the higher index of array
int get_majority_elem(vector<int> &a, int low, int high)
{
if (low > high) return -1;
if (low == high) return a[low];
int mid = (low + high) / 2;
int h1 = get_majority_elem(a, low, mid);
int h2 = get_majority_elem(a, mid + 1, high);
// calculate the majority from combined sub arrays
int me = combined(a, h1, h2, low, mid, high);
return me;
}
public class MajorityElement {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int testCases = sc.nextInt();
while(testCases-- > 0) {
int n = sc.nextInt();
int a[] = new int[n];
int maxCount = 0;
int index = -1;
for(int i = 0 ; i < n; i++) {
a[i] = sc.nextInt();
}
for(int i = 0; i < n; i++) {
int count =0;
for(int j = 0; j < n; j++) {
if(a[i] == a[j])
count++;
}
if(count > maxCount) {
maxCount = count;
index = i;
}
}
if(maxCount > n/2)
System.out.println(a[index]);
else
System.out.println(-1);
}
sc.close();
}
}
Find majority element in O(n*logn) time
A majority element occurs at least (n/2 +1) times (say L equals this value), where n is the size of the array. Hence, its obvious that 2*L > n.
Consequently, there cannot be 2 sequences of different values of length L in the array.
Now, sort the array - which will take O(n*logn) time, if you are able to do it best.
Here comes the tricky part:
In the sorted list, try underlining each sequence of length L from the beginning till the end of the array.
i.e. 1st sequence will be from 0 to L, 2nd will be 1 to (L+1),...and so on.
Observe that the element at L-th position is common in all such sequences. In other words, if a majority element exists, it will always be in median.
So, we can conclude that the element at the L-th position can be a candidate key.
Now, count the number of occurrences of the element at the L-th position. If its greater than n/2, then voila! you have your answer, else I'm sorry, the array doesn't possess any majority element.
The majority element is the element that appears more than ⌊n / 2⌋ times.
Input: nums = [3,2,2,2,3]
Output: 2
Python Code:
def majorityElement(nums):
nums.sort() or nums = sorted(nums)
return nums[len(nums)//2]
nums = [int(x) for x in input()]
print(majorityElements(nums))
I have changed and added more to this question: Majority elements in an array[] of size n is an element that appears more than n/2 times
ex:
{1,2,1,3,1} here n/2 is 2, so 1 appeared more than 2 times o/p:1
{1,2,1,2,3} here also n/2 is 2, but no element is appeard more than 2 times so o/p is "No element"
import java.io.*;
import java.util.*;
import java.lang.Math;
class Demo{
public static void main(String args[]) {
Demo d=new Demo();
int[] arr={2,2,2,3,1};
int res=d.majorityNo(arr);
int count=0;
for(int i=0;i<arr.length;i++){
if(res==arr[i]){
count++;
}
}
if(count>(arr.length/2)){
System.out.println(arr[res]);
}else{
System.out.println("No element ");
}
}
public static int majorityNo(int[] arr){
int temp=1;
int index=0;
int res=0;
for(int i=0;i<arr.length;i++){
if(arr[index]==arr[i]){
temp++;
}else{
temp--;
if(temp==0){
index=i;
temp=1;
}
}
}
return arr[index];
}
}
to find the Majority Element, Boyer–Moore Majority Vote Algorithm can be used. here's C# implementation.
public int MajorityItem(int[] array)
{
if (array == null || array.Length == 0)
{
return -1;
}
if (array.Length == 1)
{
return array[0];
}
int count = 1;
int result = array[0];
for (int i = 1; i < array.Length; i++)
{
if (array[i] == result)
{
count++;
}
else
{
count--;
if (count == 0)
{
result = array[i];
count = 1;
}
}
}
return result;
}
For finding majority of element: I was able to find majority element using sorting approach. I sorted those elements first afterwards I used the definition of majority element that it is always > n/2. I choosed the middle element and the counted it coz if it is a majority element the middle element should be majority element. after countiung I compared it with n/2. And got the result. Correct me if I am wrong.
Majority element can be found in O(n) time complexity using Moore's Voting Algorithm. Below are the two steps
Step 1: Find the candidate which is majority in the array.
Step 2: Check for validating the candidate found in step 1 for its majority.
Below is the code
def majority_element(A, N):
# A: Array and N: size of the array
res = 0
count = 1
for i in range(1, N):
if A[res] == A[i]:
count += 1
else:
count -= 1
if count == 0:
count = 1
res = i
count = 0
for i in range(N):
if A[res] == A[i]:
count += 1
if count <= N // 2:
return -1
else:
return A[res]
int result = -1;
int times = size/2;
HashMap<Integer,Integer> counterMap = new HashMap<>();
int count = 0;
for(int i = 0 ;i<size;i++) {
if(counterMap.containsKey(a[i])){
count = counterMap.get(a[i]);
}else {
count = 0;
}
counterMap.put(a[i], count+1);
}
for (Map.Entry<Integer, Integer> pair : counterMap.entrySet()) {
if(pair.getValue()>times) {
result = pair.getKey();
}
}
return result;
Sort the given array : O(nlogn).
If the array size is 7, then the majority element occurs atleast ceiling(7/2) = 4 times in the array.
After the array is sorted, it means that if the majority element is first found at position i, it is also found at position i + floor(7/2) (4 occurences).
Example - Given array A - {7,3,2,3,3,6,3}
Sort the array - {2,3,3,3,3,6,7}
The element 3 is found at position 1 (array index starting from 0.) If the position 1 + 3 = 4th element is also 3, then it means 3 is the majority element.
if we loop through the array from beginning..
compare position 0 with position 3, different elements 2 and 3.
compare position 1 with position 4, same element. We found our majority match!
Complexity - O(n)
Total time complexity - O(n).

Resources