Median of Medians algorithm misunderstanding? - c++
What I understand already
I understand that median of medians algorithm(I will denote as MoM) is a high constant factor O(N) algorithm. It finds the medians of k-groups(usually 5) and uses them as the next iteration's sets to find medians of. The pivot after finding this will be between 3/10n and 7/10n of the original set, where n is the number of iterations it took to find the one median base case.
I keep getting a segmentation fault when I run this code for MoM, but I'm not sure why. I've debugged it and believe that the issue lies with the fact that I'm calling medianOfMedian(medians, 0, medians.size()-1, medians.size()/2);. However, I thought that this was logically sound since we were supposed to recursively find the median by calling itself. Perhaps my base case isn't correct? In a tutorial by YogiBearian on youtube(a stanford professor, link: https://www.youtube.com/watch?v=YU1HfMiJzwg ), he did not state any extra base case to take care of the O(N/5) operation of recursion in MoM.
Complete Code
Note: Per suggestions, I have added a base case and used .at() function by vectors.
static const int GROUP_SIZE = 5;
/* Helper function for m of m. This function divides the array into chunks of 5
* and finds the median of each group and puts it into a vector to return.
* The last group will be sorted and the median will be found despite its uneven size.
*/
vector<int> findMedians(vector<int>& vec, int start, int end){
vector<int> medians;
for(int i = start; i <= end; i+= GROUP_SIZE){
std::sort(vec.begin()+i, min(vec.begin()+i+GROUP_SIZE, vec.end()));
medians.push_back(vec.at(min(i + (GROUP_SIZE/2), (i + end)/2)));
}
return medians;
}
/* Job is to partition the array into chunks of 5(subject to change via const)
* And then find the median of them. Do this recursively using select as well.
*/
int medianOfMedian(vector<int>& vec, int start, int end, int k){
/* Acquire the medians of the 5-groups */
vector<int> medians = findMedians(vec, start, end);
/* Find the median of this */
int pivotVal;
if(medians.size() == 1)
pivotVal = medians.at(0);
else
pivotVal = medianOfMedian(medians, 0, medians.size()-1, medians.size()/2);
/* Stealing a page from select() ... */
int pivot = partitionHelper(vec, pivotVal, start, end);
cout << "After pivoting with the value " << pivot << " we get : " << endl;
for(int i = start; i < end; i++){
cout << vec.at(i) << ", ";
}
cout << "\n\n" << endl;
usleep(10000);
int length = pivot - start + 1;
if(k < length){
return medianOfMedian(vec, k, start, pivot-1);
}
else if(k == length){
return vec[k];
}
else{
return medianOfMedian(vec, k-length, pivot+1, end);
}
}
Some extra functions for helping unit test
Here are some unit tests that I wrote for these 2 functions. Hopefully they help.
vector<int> initialize(int size, int mod){
int arr[size];
for(int i = 0; i < size; i++){
arr[i] = rand() % mod;
}
vector<int> vec(arr, arr+size);
return vec;
}
/* Unit test for findMedians */
void testFindMedians(){
const int SIZE = 36;
const int MOD = 20;
vector<int> vec = initialize(SIZE, MOD);
for(int i = 0; i < SIZE; i++){
cout << vec[i] << ", ";
}
cout << "\n\n" << endl;
vector<int> medians = findMedians(vec, 0, SIZE-1);
cout << "The 5-sorted version: " << endl;
for(int i = 0; i < SIZE; i++){
cout << vec[i] << ", ";
}
cout << "\n\n" << endl;
cout << "The medians extracted: " << endl;
for(int i = 0; i < medians.size(); i++){
cout << medians[i] << ", ";
}
cout << "\n\n" << endl;
}
/* Unit test for medianOfMedian */
void testMedianOfMedian(){
const int SIZE = 30;
const int MOD = 70;
vector<int> vec = initialize(SIZE, MOD);
cout << "Given array : " << endl;
for(int i = 0; i < SIZE; i++){
cout << vec[i] << ", ";
}
cout << "\n\n" << endl;
int median = medianOfMedian(vec, 0, vec.size()-1, vec.size()/2);
cout << "\n\nThe median is : " << median << endl;
cout << "As opposed to sorting and then showing the median... : " << endl;
std::sort(vec.begin(), vec.end());
cout << "sorted array : " << endl;
for(int i = 0; i < SIZE; i++){
if(i == SIZE/2)
cout << "**";
cout << vec[i] << ", ";
}
cout << "Median : " << vec[SIZE/2] << endl;
}
Extra section about the output that I'm getting
Given array :
7, 49, 23, 48, 20, 62, 44, 8, 43, 29, 20, 65, 42, 62, 7, 33, 37, 39, 60, 52, 53, 19, 29, 7, 50, 3, 69, 58, 56, 65,
After pivoting with the value 5 we get :
23, 29, 39, 42, 43,
After pivoting with the value 0 we get :
39,
Segmentation Fault: 11
It seems all right and dandy until the segmentation fault. I'm confident that my partition function works as well(was one of the implementations for the leetcode question).
Disclaimer: This is not a homework problem, but rather my own curiosity about the algorithm after I used quickSelect in a leetcode problem set.
Please let me know if my question proposed requires more elaboration for MVCE, thanks!
EDIT: I figured out that the recursion partition scheme is wrong in my code. As Pradhan has pointed out - I somehow have empty vectors which lead to the start and end being 0 and -1 respectively, causing me to have segmentation fault from an infinite loop of calling it. Still trying to figure this part out.
MoM always calls itself (to compute pivot), and thus exhibits infinite recursion. This violates the "prime directive" of recursive algorithms: at some point, the problem is "small" enough to not need a recursive call.
Correct Implementation
With the help of Scott's hint, I was able to give a correct implementation of this median of medians algorithm. I fixed it and realized that the main idea that I had was correct, but there were a couple errors:
My base case should be for subvectors in the size of <=5.
There were some small subtleties about whether the last number(variable end), in this case should be considered to be included or as the upper bound less than. In this implementation below I made it the upper bound less than definition.
Here it is below. I also accepted Scott's answer - thank you Scott!
/* In case someone wants to pass in the pivValue, I broke partition into 2 pieces.
*/
int pivot(vector<int>& vec, int pivot, int start, int end){
/* Now we need to go into the array with a starting left and right value. */
int left = start, right = end-1;
while(left < right){
/* Increase the left and the right values until inappropriate value comes */
while(vec.at(left) < pivot && left <= right) left++;
while(vec.at(right) > pivot && right >= left) right--;
/* In case of duplicate values, we must take care of this special case. */
if(left >= right) break;
else if(vec.at(left) == vec.at(right)){ left++; continue; }
/* Do the normal swapping */
int temp = vec.at(left);
vec.at(left) = vec.at(right);
vec.at(right) = temp;
}
return right;
}
/* Returns the k-th element of this array. */
int MoM(vector<int>& vec, int k, int start, int end){
/* Start by base case: Sort if less than 10 size
* E.x.: Size = 9, 9 - 0 = 9.
*/
if(end-start < 10){
sort(vec.begin()+start, vec.begin()+end);
return vec.at(k);
}
vector<int> medians;
/* Now sort every consecutive 5 */
for(int i = start; i < end; i+=5){
if(end - i < 10){
sort(vec.begin()+i, vec.begin()+end);
medians.push_back(vec.at((i+end)/2));
}
else{
sort(vec.begin()+i, vec.begin()+i+5);
medians.push_back(vec.at(i+2));
}
}
int median = MoM(medians, medians.size()/2, 0, medians.size());
/* use the median to pivot around */
int piv = pivot(vec, median, start, end);
int length = piv - start+1;
if(k < length){
return MoM(vec, k, start, piv);
}
else if(k > length){
return MoM(vec, k-length, piv+1, end);
}
else
return vec[k];
}
Related
C++ position in index removal of hard coded list of numbers
I have a pretty simple question. My goal for this short program is for it to display the set of numbers(which is hard coded), then have the user specify which index a number of the array should be deleted from. It then outputs the new array. This program works but has one major error. When I run it and choose position 2 for example, which should delete 45, instead deletes 34. The program outputs : 12 45 2 8 10 16 180 182 22 instead of : 12 34 2 8 10 16 180 182 22 notice that the number position I want removed instead removes in the position before the number I actually want removed, if you remember that lists start at 0. Thank you! //This program demos basic arrays #include <iostream> using namespace std; const int CAP = 10; int main() { //read index from user, delete number in position of index they specify. //when printing the list, number should be gone. int size; int list[CAP] = { 12, 34, 45, 2, 8, 10, 16, 180, 182, 22 }; size = 10; int i, delIndex; cout << "Your list is: " << endl; for (i = 0; i < CAP; i++) { cout << list[i] << endl; } cout << "\nPlease enter index to delete from: "; cin >> delIndex; for (i = delIndex; i <= 10; i++) { list[i - 1] = list[i]; } cout << "The index position you specified has been deleted." << endl; cout << "The new array is: " << endl; for (i = 0; i < (size - 1); i++) { cout << list[i] << endl; } return 0; }
Replace this: for (i = delIndex; i <= 10; i++) { list[i - 1] = list[i]; } with that: for (i = delIndex; i < size-1; i++) { list[i] = list[i+1]; }
Since you are with C++, why not just using a std vector? #include <vector> // Initialize int vv[10] = { 12, 34, 45, 2, 8, 10, 16, 180, 182, 22 }; std::vector<int> myvector(&vv[0], &vv[0]+10); There are other easier ways to initialize the vector depending on the compiler. See how to initialize a vector. Then you can just use the erase method of the vector (here I assume the user knows the indexing starts with 0, otherwise you can just put delIndex-1): myvector.erase (myvector.begin()+delIndex); You can easily iterate over the vector to show its contents (there are easier ways of doing this depending on the compiler, use the auto keyword). for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it) std::cout << ' ' << *it;
Power set of large set
I have to calculate power set of set which may have more elements upto 10^5. I tried an algo and the code below but it failed (I think cause large value of pow(2, size)). void printPowerSet(int *set, int set_size) { unsigned int pow_set_size = pow(2, set_size); int counter, j,sum=0; for(counter = 0; counter < pow_set_size; counter++) { for(j = 0; j < set_size; j++) { if(counter & (1<<j)) std::cout<<set[i]<<" "; } std::cout<<sum; sum=0; printf("\n"); } } Is there any other algorithm or how can I fix this one (if it is possible)?? OR Can you suggest me how to do it i.e. finding subset of large set. As pointed out in an answer it seems I'm stuck in X-Y problem. Basically, I need sum of all subsets of any set. Now if you can suggest me any other approach to solve the problem. Thank you.
Here is an algorithm which will print out the power set of any set that will fit in your computer's memory. Given enough time, it will print the power set of a set of length 10^5. However, "enough time" will be something like several trillion billion gazillion years. c++14 #include <iostream> #include <vector> #include <algorithm> using namespace std; #include <iostream> void printPowerset (const vector<int>& original_set) { auto print_set = [&original_set](auto first, auto last) -> ostream& { cout << '('; auto sep = ""; for ( ; first != last ; ++first, sep = ",") { cout << sep << original_set[(*first) - 1]; } return cout << ')'; }; const int n = original_set.size(); std::vector<int> index_stack(n + 1, 0); int k = 0; while(1){ if (index_stack[k]<n){ index_stack[k+1] = index_stack[k] + 1; k++; } else{ index_stack[k-1]++; k--; } if (k==0) break; print_set(begin(index_stack) + 1, begin(index_stack) + 1 + k); } print_set(begin(index_stack), begin(index_stack)) << endl; } int main(){ auto nums = vector<int> { 2, 4, 6, 8 }; printPowerset(nums); nums = vector<int> { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; printPowerset(nums); return 0; } expected results: first power set (4 items): (2)(2,4)(2,4,6)(2,4,6,8)(2,4,8)(2,6)(2,6,8)(2,8)(4)(4,6)(4,6,8)(4,8)(6)(6,8)(8)() second power set (10 items) (2)(2,4)(2,4,6)(2,4,6,8)(2,4,6,8,10)(2,4,6,8,10,12)(2,4,6,8,10,12,14)(2,4,6,8,10,12,14,16)(2,4,6,8,10,12,14,16,18)(2,4,6,8,10,12,14,16,18,20)(2,4,6,8,10,12,14,16,20)(2,4,6,8,10,12,14,18)(2,4,6,8,10,12,14,18,20)(2,4,6,8,10,12,14,20)(2,4,6,8,10,12,16)(2,4,6,8,10,12,16,18)(2,4,6,8,10,12,16,18,20)(2,4,6,8,10,12,16,20)(2,4,6,8,10,12,18)(2,4,6,8,10,12,18,20)(2,4,6,8,10,12,20)(2,4,6,8,10,14)(2,4,6,8,10,14,16)(2,4,6,8,10,14,16,18)(2,4,6,8,10,14,16,18,20)(2,4,6,8,10,14,16,20)(2,4,6,8,10,14,18)(2,4,6,8,10,14,18,20)(2,4,6,8,10,14,20)(2,4,6,8,10,16)(2,4,6,8,10,16,18)(2,4,6,8,10,16,18,20)(2,4,6,8,10,16,20)(2,4,6,8,10,18)(2,4,6,8,10,18,20)(2,4,6,8,10,20)(2,4,6,8,12)(2,4,6,8,12,14)(2,4,6,8,12,14,16)(2,4,6,8,12,14,16,18)(2,4,6,8,12,14,16,18,20)(2,4,6,8,12,14,16,20)(2,4,6,8,12,14,18)(2,4,6,8,12,14,18,20)(2,4,6,8,12,14,20)(2,4,6,8,12,16)(2,4,6,8,12,16,18)(2,4,6,8,12,16,18,20)(2,4,6,8,12,16,20)(2,4,6,8,12,18)(2,4,6,8,12,18,20)(2,4,6,8,12,20)(2,4,6,8,14)(2,4,6,8,14,16)(2,4,6,8,14,16,18)(2,4,6,8,14,16,18,20)(2,4,6,8,14,16,20)(2,4,6,8,14,18)(2,4,6,8,14,18,20)(2,4,6,8,14,20)(2,4,6,8,16)(2,4,6,8,16,18)(2,4,6,8,16,18,20)(2,4,6,8,16,20)(2,4,6,8,18)(2,4,6,8,18,20)(2,4,6,8,20)(2,4,6,10)(2,4,6,10,12)(2,4,6,10,12,14)(2,4,6,10,12,14,16)(2,4,6,10,12,14,16,18)(2,4,6,10,12,14,16,18,20)(2,4,6,10,12,14,16,20)(2,4,6,10,12,14,18)(2,4,6,10,12,14,18,20)(2,4,6,10,12,14,20)(2,4,6,10,12,16)(2,4,6,10,12,16,18)(2,4,6,10,12,16,18,20)(2,4,6,10,12,16,20)(2,4,6,10,12,18)(2,4,6,10,12,18,20)(2,4,6,10,12,20)(2,4,6,10,14)(2,4,6,10,14,16)(2,4,6,10,14,16,18)(2,4,6,10,14,16,18,20)(2,4,6,10,14,16,20)(2,4,6,10,14,18)(2,4,6,10,14,18,20)(2,4,6,10,14,20)(2,4,6,10,16)(2,4,6,10,16,18)(2,4,6,10,16,18,20)(2,4,6,10,16,20)(2,4,6,10,18)(2,4,6,10,18,20)(2,4,6,10,20)(2,4,6,12)(2,4,6,12,14)(2,4,6,12,14,16)(2,4,6,12,14,16,18)(2,4,6,12,14,16,18,20)(2,4,6,12,14,16,20)(2,4,6,12,14,18)(2,4,6,12,14,18,20)(2,4,6,12,14,20)(2,4,6,12,16)(2,4,6,12,16,18)(2,4,6,12,16,18,20)(2,4,6,12,16,20)(2,4,6,12,18)(2,4,6,12,18,20)(2,4,6,12,20)(2,4,6,14)(2,4,6,14,16)(2,4,6,14,16,18)(2,4,6,14,16,18,20)(2,4,6,14,16,20)(2,4,6,14,18)(2,4,6,14,18,20)(2,4,6,14,20)(2,4,6,16)(2,4,6,16,18)(2,4,6,16,18,20)(2,4,6,16,20)(2,4,6,18)(2,4,6,18,20)(2,4,6,20)(2,4,8)(2,4,8,10)(2,4,8,10,12)(2,4,8,10,12,14)(2,4,8,10,12,14,16)(2,4,8,10,12,14,16,18)(2,4,8,10,12,14,16,18,20)(2,4,8,10,12,14,16,20)(2,4,8,10,12,14,18)(2,4,8,10,12,14,18,20)(2,4,8,10,12,14,20)(2,4,8,10,12,16)(2,4,8,10,12,16,18)(2,4,8,10,12,16,18,20)(2,4,8,10,12,16,20)(2,4,8,10,12,18)(2,4,8,10,12,18,20)(2,4,8,10,12,20)(2,4,8,10,14)(2,4,8,10,14,16)(2,4,8,10,14,16,18)(2,4,8,10,14,16,18,20)(2,4,8,10,14,16,20)(2,4,8,10,14,18)(2,4,8,10,14,18,20)(2,4,8,10,14,20)(2,4,8,10,16)(2,4,8,10,16,18)(2,4,8,10,16,18,20)(2,4,8,10,16,20)(2,4,8,10,18)(2,4,8,10,18,20)(2,4,8,10,20)(2,4,8,12)(2,4,8,12,14)(2,4,8,12,14,16)(2,4,8,12,14,16,18)(2,4,8,12,14,16,18,20)(2,4,8,12,14,16,20)(2,4,8,12,14,18)(2,4,8,12,14,18,20)(2,4,8,12,14,20)(2,4,8,12,16)(2,4,8,12,16,18)(2,4,8,12,16,18,20)(2,4,8,12,16,20)(2,4,8,12,18)(2,4,8,12,18,20)(2,4,8,12,20)(2,4,8,14)(2,4,8,14,16)(2,4,8,14,16,18)(2,4,8,14,16,18,20)(2,4,8,14,16,20)(2,4,8,14,18)(2,4,8,14,18,20)(2,4,8,14,20)(2,4,8,16)(2,4,8,16,18)(2,4,8,16,18,20)(2,4,8,16,20)(2,4,8,18)(2,4,8,18,20)(2,4,8,20)(2,4,10)(2,4,10,12)(2,4,10,12,14)(2,4,10,12,14,16)(2,4,10,12,14,16,18)(2,4,10,12,14,16,18,20)(2,4,10,12,14,16,20)(2,4,10,12,14,18)(2,4,10,12,14,18,20)(2,4,10,12,14,20)(2,4,10,12,16)(2,4,10,12,16,18)(2,4,10,12,16,18,20)(2,4,10,12,16,20)(2,4,10,12,18)(2,4,10,12,18,20)(2,4,10,12,20)(2,4,10,14)(2,4,10,14,16)(2,4,10,14,16,18)(2,4,10,14,16,18,20)(2,4,10,14,16,20)(2,4,10,14,18)(2,4,10,14,18,20)(2,4,10,14,20)(2,4,10,16)(2,4,10,16,18)(2,4,10,16,18,20)(2,4,10,16,20)(2,4,10,18)(2,4,10,18,20)(2,4,10,20)(2,4,12)(2,4,12,14)(2,4,12,14,16)(2,4,12,14,16,18)(2,4,12,14,16,18,20)(2,4,12,14,16,20)(2,4,12,14,18)(2,4,12,14,18,20)(2,4,12,14,20)(2,4,12,16)(2,4,12,16,18)(2,4,12,16,18,20)(2,4,12,16,20)(2,4,12,18)(2,4,12,18,20)(2,4,12,20)(2,4,14)(2,4,14,16)(2,4,14,16,18)(2,4,14,16,18,20)(2,4,14,16,20)(2,4,14,18)(2,4,14,18,20)(2,4,14,20)(2,4,16)(2,4,16,18)(2,4,16,18,20)(2,4,16,20)(2,4,18)(2,4,18,20)(2,4,20)(2,6)(2,6,8)(2,6,8,10)(2,6,8,10,12)(2,6,8,10,12,14)(2,6,8,10,12,14,16)(2,6,8,10,12,14,16,18)(2,6,8,10,12,14,16,18,20)(2,6,8,10,12,14,16,20)(2,6,8,10,12,14,18)(2,6,8,10,12,14,18,20)(2,6,8,10,12,14,20)(2,6,8,10,12,16)(2,6,8,10,12,16,18)(2,6,8,10,12,16,18,20)(2,6,8,10,12,16,20)(2,6,8,10,12,18)(2,6,8,10,12,18,20)(2,6,8,10,12,20)(2,6,8,10,14)(2,6,8,10,14,16)(2,6,8,10,14,16,18)(2,6,8,10,14,16,18,20)(2,6,8,10,14,16,20)(2,6,8,10,14,18)(2,6,8,10,14,18,20)(2,6,8,10,14,20)(2,6,8,10,16)(2,6,8,10,16,18)(2,6,8,10,16,18,20)(2,6,8,10,16,20)(2,6,8,10,18)(2,6,8,10,18,20)(2,6,8,10,20)(2,6,8,12)(2,6,8,12,14)(2,6,8,12,14,16)(2,6,8,12,14,16,18)(2,6,8,12,14,16,18,20)(2,6,8,12,14,16,20)(2,6,8,12,14,18)(2,6,8,12,14,18,20)(2,6,8,12,14,20)(2,6,8,12,16)(2,6,8,12,16,18)(2,6,8,12,16,18,20)(2,6,8,12,16,20)(2,6,8,12,18)(2,6,8,12,18,20)(2,6,8,12,20)(2,6,8,14)(2,6,8,14,16)(2,6,8,14,16,18)(2,6,8,14,16,18,20)(2,6,8,14,16,20)(2,6,8,14,18)(2,6,8,14,18,20)(2,6,8,14,20)(2,6,8,16)(2,6,8,16,18)(2,6,8,16,18,20)(2,6,8,16,20)(2,6,8,18)(2,6,8,18,20)(2,6,8,20)(2,6,10)(2,6,10,12)(2,6,10,12,14)(2,6,10,12,14,16)(2,6,10,12,14,16,18)(2,6,10,12,14,16,18,20)(2,6,10,12,14,16,20)(2,6,10,12,14,18)(2,6,10,12,14,18,20)(2,6,10,12,14,20)(2,6,10,12,16)(2,6,10,12,16,18)(2,6,10,12,16,18,20)(2,6,10,12,16,20)(2,6,10,12,18)(2,6,10,12,18,20)(2,6,10,12,20)(2,6,10,14)(2,6,10,14,16)(2,6,10,14,16,18)(2,6,10,14,16,18,20)(2,6,10,14,16,20)(2,6,10,14,18)(2,6,10,14,18,20)(2,6,10,14,20)(2,6,10,16)(2,6,10,16,18)(2,6,10,16,18,20)(2,6,10,16,20)(2,6,10,18)(2,6,10,18,20)(2,6,10,20)(2,6,12)(2,6,12,14)(2,6,12,14,16)(2,6,12,14,16,18)(2,6,12,14,16,18,20)(2,6,12,14,16,20)(2,6,12,14,18)(2,6,12,14,18,20)(2,6,12,14,20)(2,6,12,16)(2,6,12,16,18)(2,6,12,16,18,20)(2,6,12,16,20)(2,6,12,18)(2,6,12,18,20)(2,6,12,20)(2,6,14)(2,6,14,16)(2,6,14,16,18)(2,6,14,16,18,20)(2,6,14,16,20)(2,6,14,18)(2,6,14,18,20)(2,6,14,20)(2,6,16)(2,6,16,18)(2,6,16,18,20)(2,6,16,20)(2,6,18)(2,6,18,20)(2,6,20)(2,8)(2,8,10)(2,8,10,12)(2,8,10,12,14)(2,8,10,12,14,16)(2,8,10,12,14,16,18)(2,8,10,12,14,16,18,20)(2,8,10,12,14,16,20)(2,8,10,12,14,18)(2,8,10,12,14,18,20)(2,8,10,12,14,20)(2,8,10,12,16)(2,8,10,12,16,18)(2,8,10,12,16,18,20)(2,8,10,12,16,20)(2,8,10,12,18)(2,8,10,12,18,20)(2,8,10,12,20)(2,8,10,14)(2,8,10,14,16)(2,8,10,14,16,18)(2,8,10,14,16,18,20)(2,8,10,14,16,20)(2,8,10,14,18)(2,8,10,14,18,20)(2,8,10,14,20)(2,8,10,16)(2,8,10,16,18)(2,8,10,16,18,20)(2,8,10,16,20)(2,8,10,18)(2,8,10,18,20)(2,8,10,20)(2,8,12)(2,8,12,14)(2,8,12,14,16)(2,8,12,14,16,18)(2,8,12,14,16,18,20)(2,8,12,14,16,20)(2,8,12,14,18)(2,8,12,14,18,20)(2,8,12,14,20)(2,8,12,16)(2,8,12,16,18)(2,8,12,16,18,20)(2,8,12,16,20)(2,8,12,18)(2,8,12,18,20)(2,8,12,20)(2,8,14)(2,8,14,16)(2,8,14,16,18)(2,8,14,16,18,20)(2,8,14,16,20)(2,8,14,18)(2,8,14,18,20)(2,8,14,20)(2,8,16)(2,8,16,18)(2,8,16,18,20)(2,8,16,20)(2,8,18)(2,8,18,20)(2,8,20)(2,10)(2,10,12)(2,10,12,14)(2,10,12,14,16)(2,10,12,14,16,18)(2,10,12,14,16,18,20)(2,10,12,14,16,20)(2,10,12,14,18)(2,10,12,14,18,20)(2,10,12,14,20)(2,10,12,16)(2,10,12,16,18)(2,10,12,16,18,20)(2,10,12,16,20)(2,10,12,18)(2,10,12,18,20)(2,10,12,20)(2,10,14)(2,10,14,16)(2,10,14,16,18)(2,10,14,16,18,20)(2,10,14,16,20)(2,10,14,18)(2,10,14,18,20)(2,10,14,20)(2,10,16)(2,10,16,18)(2,10,16,18,20)(2,10,16,20)(2,10,18)(2,10,18,20)(2,10,20)(2,12)(2,12,14)(2,12,14,16)(2,12,14,16,18)(2,12,14,16,18,20)(2,12,14,16,20)(2,12,14,18)(2,12,14,18,20)(2,12,14,20)(2,12,16)(2,12,16,18)(2,12,16,18,20)(2,12,16,20)(2,12,18)(2,12,18,20)(2,12,20)(2,14)(2,14,16)(2,14,16,18)(2,14,16,18,20)(2,14,16,20)(2,14,18)(2,14,18,20)(2,14,20)(2,16)(2,16,18)(2,16,18,20)(2,16,20)(2,18)(2,18,20)(2,20)(4)(4,6)(4,6,8)(4,6,8,10)(4,6,8,10,12)(4,6,8,10,12,14)(4,6,8,10,12,14,16)(4,6,8,10,12,14,16,18)(4,6,8,10,12,14,16,18,20)(4,6,8,10,12,14,16,20)(4,6,8,10,12,14,18)(4,6,8,10,12,14,18,20)(4,6,8,10,12,14,20)(4,6,8,10,12,16)(4,6,8,10,12,16,18)(4,6,8,10,12,16,18,20)(4,6,8,10,12,16,20)(4,6,8,10,12,18)(4,6,8,10,12,18,20)(4,6,8,10,12,20)(4,6,8,10,14)(4,6,8,10,14,16)(4,6,8,10,14,16,18)(4,6,8,10,14,16,18,20)(4,6,8,10,14,16,20)(4,6,8,10,14,18)(4,6,8,10,14,18,20)(4,6,8,10,14,20)(4,6,8,10,16)(4,6,8,10,16,18)(4,6,8,10,16,18,20)(4,6,8,10,16,20)(4,6,8,10,18)(4,6,8,10,18,20)(4,6,8,10,20)(4,6,8,12)(4,6,8,12,14)(4,6,8,12,14,16)(4,6,8,12,14,16,18)(4,6,8,12,14,16,18,20)(4,6,8,12,14,16,20)(4,6,8,12,14,18)(4,6,8,12,14,18,20)(4,6,8,12,14,20)(4,6,8,12,16)(4,6,8,12,16,18)(4,6,8,12,16,18,20)(4,6,8,12,16,20)(4,6,8,12,18)(4,6,8,12,18,20)(4,6,8,12,20)(4,6,8,14)(4,6,8,14,16)(4,6,8,14,16,18)(4,6,8,14,16,18,20)(4,6,8,14,16,20)(4,6,8,14,18)(4,6,8,14,18,20)(4,6,8,14,20)(4,6,8,16)(4,6,8,16,18)(4,6,8,16,18,20)(4,6,8,16,20)(4,6,8,18)(4,6,8,18,20)(4,6,8,20)(4,6,10)(4,6,10,12)(4,6,10,12,14)(4,6,10,12,14,16)(4,6,10,12,14,16,18)(4,6,10,12,14,16,18,20)(4,6,10,12,14,16,20)(4,6,10,12,14,18)(4,6,10,12,14,18,20)(4,6,10,12,14,20)(4,6,10,12,16)(4,6,10,12,16,18)(4,6,10,12,16,18,20)(4,6,10,12,16,20)(4,6,10,12,18)(4,6,10,12,18,20)(4,6,10,12,20)(4,6,10,14)(4,6,10,14,16)(4,6,10,14,16,18)(4,6,10,14,16,18,20)(4,6,10,14,16,20)(4,6,10,14,18)(4,6,10,14,18,20)(4,6,10,14,20)(4,6,10,16)(4,6,10,16,18)(4,6,10,16,18,20)(4,6,10,16,20)(4,6,10,18)(4,6,10,18,20)(4,6,10,20)(4,6,12)(4,6,12,14)(4,6,12,14,16)(4,6,12,14,16,18)(4,6,12,14,16,18,20)(4,6,12,14,16,20)(4,6,12,14,18)(4,6,12,14,18,20)(4,6,12,14,20)(4,6,12,16)(4,6,12,16,18)(4,6,12,16,18,20)(4,6,12,16,20)(4,6,12,18)(4,6,12,18,20)(4,6,12,20)(4,6,14)(4,6,14,16)(4,6,14,16,18)(4,6,14,16,18,20)(4,6,14,16,20)(4,6,14,18)(4,6,14,18,20)(4,6,14,20)(4,6,16)(4,6,16,18)(4,6,16,18,20)(4,6,16,20)(4,6,18)(4,6,18,20)(4,6,20)(4,8)(4,8,10)(4,8,10,12)(4,8,10,12,14)(4,8,10,12,14,16)(4,8,10,12,14,16,18)(4,8,10,12,14,16,18,20)(4,8,10,12,14,16,20)(4,8,10,12,14,18)(4,8,10,12,14,18,20)(4,8,10,12,14,20)(4,8,10,12,16)(4,8,10,12,16,18)(4,8,10,12,16,18,20)(4,8,10,12,16,20)(4,8,10,12,18)(4,8,10,12,18,20)(4,8,10,12,20)(4,8,10,14)(4,8,10,14,16)(4,8,10,14,16,18)(4,8,10,14,16,18,20)(4,8,10,14,16,20)(4,8,10,14,18)(4,8,10,14,18,20)(4,8,10,14,20)(4,8,10,16)(4,8,10,16,18)(4,8,10,16,18,20)(4,8,10,16,20)(4,8,10,18)(4,8,10,18,20)(4,8,10,20)(4,8,12)(4,8,12,14)(4,8,12,14,16)(4,8,12,14,16,18)(4,8,12,14,16,18,20)(4,8,12,14,16,20)(4,8,12,14,18)(4,8,12,14,18,20)(4,8,12,14,20)(4,8,12,16)(4,8,12,16,18)(4,8,12,16,18,20)(4,8,12,16,20)(4,8,12,18)(4,8,12,18,20)(4,8,12,20)(4,8,14)(4,8,14,16)(4,8,14,16,18)(4,8,14,16,18,20)(4,8,14,16,20)(4,8,14,18)(4,8,14,18,20)(4,8,14,20)(4,8,16)(4,8,16,18)(4,8,16,18,20)(4,8,16,20)(4,8,18)(4,8,18,20)(4,8,20)(4,10)(4,10,12)(4,10,12,14)(4,10,12,14,16)(4,10,12,14,16,18)(4,10,12,14,16,18,20)(4,10,12,14,16,20)(4,10,12,14,18)(4,10,12,14,18,20)(4,10,12,14,20)(4,10,12,16)(4,10,12,16,18)(4,10,12,16,18,20)(4,10,12,16,20)(4,10,12,18)(4,10,12,18,20)(4,10,12,20)(4,10,14)(4,10,14,16)(4,10,14,16,18)(4,10,14,16,18,20)(4,10,14,16,20)(4,10,14,18)(4,10,14,18,20)(4,10,14,20)(4,10,16)(4,10,16,18)(4,10,16,18,20)(4,10,16,20)(4,10,18)(4,10,18,20)(4,10,20)(4,12)(4,12,14)(4,12,14,16)(4,12,14,16,18)(4,12,14,16,18,20)(4,12,14,16,20)(4,12,14,18)(4,12,14,18,20)(4,12,14,20)(4,12,16)(4,12,16,18)(4,12,16,18,20)(4,12,16,20)(4,12,18)(4,12,18,20)(4,12,20)(4,14)(4,14,16)(4,14,16,18)(4,14,16,18,20)(4,14,16,20)(4,14,18)(4,14,18,20)(4,14,20)(4,16)(4,16,18)(4,16,18,20)(4,16,20)(4,18)(4,18,20)(4,20)(6)(6,8)(6,8,10)(6,8,10,12)(6,8,10,12,14)(6,8,10,12,14,16)(6,8,10,12,14,16,18)(6,8,10,12,14,16,18,20)(6,8,10,12,14,16,20)(6,8,10,12,14,18)(6,8,10,12,14,18,20)(6,8,10,12,14,20)(6,8,10,12,16)(6,8,10,12,16,18)(6,8,10,12,16,18,20)(6,8,10,12,16,20)(6,8,10,12,18)(6,8,10,12,18,20)(6,8,10,12,20)(6,8,10,14)(6,8,10,14,16)(6,8,10,14,16,18)(6,8,10,14,16,18,20)(6,8,10,14,16,20)(6,8,10,14,18)(6,8,10,14,18,20)(6,8,10,14,20)(6,8,10,16)(6,8,10,16,18)(6,8,10,16,18,20)(6,8,10,16,20)(6,8,10,18)(6,8,10,18,20)(6,8,10,20)(6,8,12)(6,8,12,14)(6,8,12,14,16)(6,8,12,14,16,18)(6,8,12,14,16,18,20)(6,8,12,14,16,20)(6,8,12,14,18)(6,8,12,14,18,20)(6,8,12,14,20)(6,8,12,16)(6,8,12,16,18)(6,8,12,16,18,20)(6,8,12,16,20)(6,8,12,18)(6,8,12,18,20)(6,8,12,20)(6,8,14)(6,8,14,16)(6,8,14,16,18)(6,8,14,16,18,20)(6,8,14,16,20)(6,8,14,18)(6,8,14,18,20)(6,8,14,20)(6,8,16)(6,8,16,18)(6,8,16,18,20)(6,8,16,20)(6,8,18)(6,8,18,20)(6,8,20)(6,10)(6,10,12)(6,10,12,14)(6,10,12,14,16)(6,10,12,14,16,18)(6,10,12,14,16,18,20)(6,10,12,14,16,20)(6,10,12,14,18)(6,10,12,14,18,20)(6,10,12,14,20)(6,10,12,16)(6,10,12,16,18)(6,10,12,16,18,20)(6,10,12,16,20)(6,10,12,18)(6,10,12,18,20)(6,10,12,20)(6,10,14)(6,10,14,16)(6,10,14,16,18)(6,10,14,16,18,20)(6,10,14,16,20)(6,10,14,18)(6,10,14,18,20)(6,10,14,20)(6,10,16)(6,10,16,18)(6,10,16,18,20)(6,10,16,20)(6,10,18)(6,10,18,20)(6,10,20)(6,12)(6,12,14)(6,12,14,16)(6,12,14,16,18)(6,12,14,16,18,20)(6,12,14,16,20)(6,12,14,18)(6,12,14,18,20)(6,12,14,20)(6,12,16)(6,12,16,18)(6,12,16,18,20)(6,12,16,20)(6,12,18)(6,12,18,20)(6,12,20)(6,14)(6,14,16)(6,14,16,18)(6,14,16,18,20)(6,14,16,20)(6,14,18)(6,14,18,20)(6,14,20)(6,16)(6,16,18)(6,16,18,20)(6,16,20)(6,18)(6,18,20)(6,20)(8)(8,10)(8,10,12)(8,10,12,14)(8,10,12,14,16)(8,10,12,14,16,18)(8,10,12,14,16,18,20)(8,10,12,14,16,20)(8,10,12,14,18)(8,10,12,14,18,20)(8,10,12,14,20)(8,10,12,16)(8,10,12,16,18)(8,10,12,16,18,20)(8,10,12,16,20)(8,10,12,18)(8,10,12,18,20)(8,10,12,20)(8,10,14)(8,10,14,16)(8,10,14,16,18)(8,10,14,16,18,20)(8,10,14,16,20)(8,10,14,18)(8,10,14,18,20)(8,10,14,20)(8,10,16)(8,10,16,18)(8,10,16,18,20)(8,10,16,20)(8,10,18)(8,10,18,20)(8,10,20)(8,12)(8,12,14)(8,12,14,16)(8,12,14,16,18)(8,12,14,16,18,20)(8,12,14,16,20)(8,12,14,18)(8,12,14,18,20)(8,12,14,20)(8,12,16)(8,12,16,18)(8,12,16,18,20)(8,12,16,20)(8,12,18)(8,12,18,20)(8,12,20)(8,14)(8,14,16)(8,14,16,18)(8,14,16,18,20)(8,14,16,20)(8,14,18)(8,14,18,20)(8,14,20)(8,16)(8,16,18)(8,16,18,20)(8,16,20)(8,18)(8,18,20)(8,20)(10)(10,12)(10,12,14)(10,12,14,16)(10,12,14,16,18)(10,12,14,16,18,20)(10,12,14,16,20)(10,12,14,18)(10,12,14,18,20)(10,12,14,20)(10,12,16)(10,12,16,18)(10,12,16,18,20)(10,12,16,20)(10,12,18)(10,12,18,20)(10,12,20)(10,14)(10,14,16)(10,14,16,18)(10,14,16,18,20)(10,14,16,20)(10,14,18)(10,14,18,20)(10,14,20)(10,16)(10,16,18)(10,16,18,20)(10,16,20)(10,18)(10,18,20)(10,20)(12)(12,14)(12,14,16)(12,14,16,18)(12,14,16,18,20)(12,14,16,20)(12,14,18)(12,14,18,20)(12,14,20)(12,16)(12,16,18)(12,16,18,20)(12,16,20)(12,18)(12,18,20)(12,20)(14)(14,16)(14,16,18)(14,16,18,20)(14,16,20)(14,18)(14,18,20)(14,20)(16)(16,18)(16,18,20)(16,20)(18)(18,20)(20)()
Since number of elements in the set can go upto 10^5 and hence the size of the set will go upto 2^(10^5) which is huge. You can just either print it or if you want to store it , store it in a file.
It is not possible, as you pointed out yourself power set contains pow(2, size) no of elements. You need to print the entire set that can only be done by generating the set using backtracking, there is nothing better. To find sum of all subsets of a given set is however a simpler problem. If the no of elements is n, then each element in the array occurs 2^(n-1) times in the power set. Pseudo code : int sum = 0; for(int i = 0;i < n;i++){ sum += ( set[i] * ( 1 << (n-1) ) ); //pow(2, n-1) == 1 << (n-1) } cout << sum << endl; You would need a Big Integer Library for larger values of n.
finding minimum number of jumps
Working on below algorithm puzzle of finding minimum number of jumps. Posted detailed problem statement and two code versions to resolve this issue. I have did testing and it seems both version works, and my 2nd version is an optimized version of version one code, which makes i starts from i=maxIndex, other than continuous increase, which could save time by not iteration all the slots of the array. My question is, wondering if my 2nd version code is 100% correct? If anyone found any logical issues, appreciate for pointing out. Problem Statement Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Your goal is to reach the last index in the minimum number of jumps. For example: Given array A = [2,3,1,1,4] The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.) First version code class Solution { public: int jump(vector<int>& nums) { int i = 0, n = nums.size(), step = 0, end = 0, maxend = 0; while (end < n - 1) { step++; for (;i <= end; i++) { maxend = max(maxend, i + nums[i]); if (maxend >= n - 1) return step; } if(end == maxend) break; end = maxend; } return n == 1 ? 0 : -1; } }; 2nd version code class Solution { public: int jump(vector<int>& nums) { int i = 0, n = nums.size(), step = 0, end = 0, maxend = 0; int maxIndex = 0; while (end < n - 1) { step++; for (i=maxIndex;i <= end; i++) { if ((i + nums[i]) > maxend) { maxend = i + nums[i]; maxIndex = i; } if (maxend >= n - 1) return step; } if(end == maxend) break; end = maxend; } return n == 1 ? 0 : -1; } }; thanks in advance, Lin
The best way is always to test it. A human cannot always think about special cases but a automated test can cover the most of speciale cases. If you think that your first version works well, you can compare the result of the first with the second one. Here an exemple: /* * arraySize : array size to use for the test * min : min jump in the array * max : max jump in the array */ void testJumps(int arraySize, int min, int max){ static int counter = 0; std::cout << "-----------Test " << counter << "------------" << std::endl; std::cout << "Array size : " << arraySize << " Minimum Jump : " << min << " Max Jump" << max << std::endl; //Create vector with random numbers std::vector<int> vecNumbers(arraySize, 0); for(unsigned int i = 0; i < vecNumbers.size(); i++) vecNumbers[i] = rand() % max + min; //Value of first function int iVersion1 = jump1(vecNumbers); //Second fucntion int iVersion2 = jump2(vecNumbers); assert(iVersion1 == iVersion2); std::cout << "Test " << counter << " succeeded" << std::endl; std::cout << "-----------------------" << std::endl; counter++; } int main() { //Two test testJumps(10, 1, 100); testJumps(20, 10, 200); //You can even make a loop of test //... }
Vector cannot be overwritten
I'm trying to write a program for university. The goal of the program is to make a nurse schedule for a hospital. However, i'm really stuck for the moment. Below you can find one function of the program. The input for the function is a roster which consists of the shift each nurse has to perform on each day. In this example, we have 32 rows (32 nurses) and 28 columns (representing 28 days). Each cell contains a number from 0 to 6, indicating a day off (0) or a certain shift (1 to 6). The function should calculate for each day, how many nurses are scheduled for a certain shift. For example, on the first day, there are 8 nurses which perform shift 2, 6 shift 3 and so forth. The output of the function is a double vector. I think the function is mostly correct but when I call it for different rosters the program always gives the first roster gave. void calculate_nbr_nurses_per_shift(vector<vector<int>> roster1) { for (int i = 0; i < get_nbr_days(); i++) { vector<int> nurses_per_shift; int nbr_nurses_free = 0; int nbr_nurses_shift1 = 0; int nbr_nurses_shift2 = 0; int nbr_nurses_shift3 = 0; int nbr_nurses_shift4 = 0; int nbr_nurses_shift5 = 0; int nbr_nurses_shift6 = 0; for (int j = 0; j < get_nbr_nurses(); j++) { if (roster1[j][i] == 0) nbr_nurses_free += 1; if (roster1[j][i] == 1) nbr_nurses_shift1 += 1; if (roster1[j][i] == 2) nbr_nurses_shift2 += 1; if (roster1[j][i] == 3) nbr_nurses_shift3 += 1; if (roster1[j][i] == 4) nbr_nurses_shift4 += 1; if (roster1[j][i] == 5) nbr_nurses_shift5 += 1; if (roster1[j][i] == 6) nbr_nurses_shift6 += 1; } nurses_per_shift.push_back(nbr_nurses_shift1); nurses_per_shift.push_back(nbr_nurses_shift2); nurses_per_shift.push_back(nbr_nurses_shift3); nurses_per_shift.push_back(nbr_nurses_shift4); nurses_per_shift.push_back(nbr_nurses_shift5); nurses_per_shift.push_back(nbr_nurses_shift6); nurses_per_shift.push_back(nbr_nurses_free); nbr_nurses_per_shift_per_day.push_back(nurses_per_shift); } } Here you can see the program: Get_shift_assignment() and schedule_LD are other rosters. void test_schedule_function() { calculate_nbr_nurses_per_shift(schedule_LD); calculate_nbr_nurses_per_shift(get_shift_assignment()); calculate_coverage_deficit(); } One more function you need to fully understand the problem is this one: void calculate_coverage_deficit() { int deficit = 0; for (int i = 0; i < get_nbr_days(); i++) { vector<int> deficit_day; for (int j = 0; j < get_nbr_shifts(); j++) { deficit = get_staffing_requirements()[j] - nbr_nurses_per_shift_per_day[i][j]; deficit_day.push_back(deficit); } nurses_deficit.push_back(deficit_day); } cout << "Day 1, shift 1: there is a deficit of " << nurses_deficit[0][0] << " nurses." << endl; cout << "Day 1, shift 2: there is a deficit of " << nurses_deficit[0][1] << " nurses." << endl; cout << "Day 1, shift 3: there is a deficit of " << nurses_deficit[0][2] << " nurses." << endl; cout << "Day 1, shift 4: there is a deficit of " << nurses_deficit[0][3] << " nurses." << endl; } So the problem is that each time I run this program it always gives me the deficits of the first roster. In this case, this is Schedule_LD. When I first run the function with input roster get_shift_assignment() than he gives me the deficits for that roster. Apparently the nbr_nurses_per_shift_per_day[][] vector is not overwritten the second time I run the function and I don't know how to fix this... Any help would be greatly appreciated.
Let me try to summarize the comments: By using global variables to return values from your functions it is very likely, that you forgot to remove older results from one or more of your global variables before calling functions again. To get around this, return your results from the function instead. Ex: vector<vector<int>> calculate_nbr_nurses_per_shift(vector<vector<int>> roster1) { vector<int> nbr_nurses_per_shift_per_day; // Create the result vector ... // Do your calculations return nbr_nurses_per_shift_per_day; } or if you do not want to return a vector: void calculate_nbr_nurses_per_shift(vector<vector<int>> roster1, vector<vector<int>> nbr_nurses_per_shift_per_day) { ... // Do your calculations } But clearly, the first variant is a lot less error-prone (in the second example you can forget to clear nbr_of_nurses again) and most compilers will optimize the return nbr_nurses_per_shift_per_day so the whole vector does not get copied. The second possible issue is that ´get_nbr_days()´ might return numbers that are larger or smaller than the actual size of your vector. To work around this, use either the size() method of vector or use iterators instead. Your first function would then look like this: vector<vector<int>> calculate_nbr_nurses_per_shift(vector<vector<int>> roster1) { vector<vector<int>> nbr_nurses_per_shift_per_day; for (vector<vector<int>>::iterator shiftsOnDay = roster1.begin(); shiftsOnDay != roster1.end(); ++shiftsOnDay) { vector<int> nurses_per_shift(6, 0); // Create vector with 6 elements initialized to 0 for (vector<int>::iterator shift = shiftsOnDay->begin(); shift != shiftsOnDay->end(); ++shift) { if (*shift == 0) nurses_per_shift[5]++; else nurses_per_shift[*shift - 1]++; // This code relies on shift only containing meaningful values } nbr_nurses_per_shift_per_day.push_back(nurses_per_shift); } return nbr_nurses_per_shift_per_day; }
Divide and Conquer array algorithm ++
I'm trying to implement a function that will look at each element of an array and determine if that particular element is larger than one INT and less than another INT. For example: Return true if Arr[5] is >i && < u I have this as a basic algorithm, which works but I want to create a more efficient piece of code, by using the 'divide and conquer' methodology, however I'm having problems using recursion to make it count and all examples I've seen only deal with one point of comparison, not two. can anyone shed some light on the situation. (http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm) My original code (linear): int SimpleSort(int length) { int A[] = {25,5,20,10,50}; int i = 25; //Less Than int u = 2; //Greater Than for(int Count = 0; Count < length; Count++) //Counter { if (A[Count] <= i && A[Count] >= u) //Checker return true; } return false; } Example code from what I've picked up of this so far(with no luck after many hours of working on various things, and using different example code: int A[] = {5,10,25,30,50,100,200,500,1000,2000}; int i = 10; //Less Than int u = 5; //Greater Than int min = 1; int max = length; int mid = (min+max)/2; if (i < A[mid] && u > A[mid]) { min = mid + 1; } else { max = mid - 1; } Until i <= A1[mid] && u >= A1[mid]) If this question is not clear I'm sorry, do ask if you need me to elaborate on anything.
Assuming your input vector is always sorted, I think something like this may work for you. This is the simplest form I could come up with, and the performance is O(log n): bool inRange(int lval, int uval, int ar[], size_t n) { if (0 == n) return false; size_t mid = n/2; if (ar[mid] >= std::min(lval,uval)) { if (ar[mid] <= std::max(lval,uval)) return true; return inRange(lval, uval, ar, mid); } return inRange(lval, uval, ar+mid+1, n-mid-1); } This uses implied range differencing; i.e. it always uses the lower of the two values as the lower-bound, and the higher of the two as the upper-bound. If your usage mandates that input values for lval and uval are to be treated as gospel, and therfore any invoke where lval > uval should return false (since it is impossible) you can remove the std::min() and std::max() expansions. In either case, you can further increase performance by making an outter front-loader and pre-checking the order of lval and uval to either (a) returning immediately as false if absolute ordering is required and lval > uval, or (b) predetermine lval and uval in proper order if range-differencing is the requirement. Examples of both such outter wrappers are explored below: // search for any ar[i] such that (lval <= ar[i] <= uval) // assumes ar[] is sorted, and (lval <= uval). bool inRange_(int lval, int uval, int ar[], size_t n) { if (0 == n) return false; size_t mid = n/2; if (ar[mid] >= lval) { if (ar[mid] <= uval) return true; return inRange_(lval, uval, ar, mid); } return inRange_(lval, uval, ar+mid+1, n-mid-1); } // use lval and uval as an hard range of [lval,uval]. // i.e. short-circuit the impossible case of lower-bound // being greater than upper-bound. bool inRangeAbs(int lval, int uval, int ar[], size_t n) { if (lval > uval) return false; return inRange_(lval, uval, ar, n); } // use lval and uval as un-ordered limits. i.e always use either // [lval,uval] or [uval,lval], depending on their values. bool inRange(int lval, int uval, int ar[], size_t n) { return inRange_(std::min(lval,uval), std::max(lval,uval), ar, n); } I have left the one I think you want as inRange. The unit tests performed to hopefully cover main and edge cases are below along with the resulting output. #include <iostream> #include <algorithm> #include <vector> #include <iomanip> #include <iterator> int main(int argc, char *argv[]) { int A[] = {5,10,25,30,50,100,200,500,1000,2000}; size_t ALen = sizeof(A)/sizeof(A[0]); srand((unsigned int)time(NULL)); // inner boundary tests (should all answer true) cout << inRange(5, 25, A, ALen) << endl; cout << inRange(1800, 2000, A, ALen) << endl; // limit tests (should all answer true) cout << inRange(0, 5, A, ALen) << endl; cout << inRange(2000, 3000, A, ALen) << endl; // midrange tests. (should all answer true) cout << inRange(26, 31, A, ALen) << endl; cout << inRange(99, 201, A, ALen) << endl; cout << inRange(6, 10, A, ALen) << endl; cout << inRange(501, 1500, A, ALen) << endl; // identity tests. (should all answer true) cout << inRange(5, 5, A, ALen) << endl; cout << inRange(25, 25, A, ALen) << endl; cout << inRange(100, 100, A, ALen) << endl; cout << inRange(1000, 1000, A, ALen) << endl; // test single-element top-and-bottom cases cout << inRange(0,5,A,1) << endl; cout << inRange(5,5,A,1) << endl; // oo-range tests (should all answer false) cout << inRange(1, 4, A, ALen) << endl; cout << inRange(2001, 2500, A, ALen) << endl; cout << inRange(1, 1, A, 0) << endl; // performance on LARGE arrays. const size_t N = 2000000; cout << "Building array of " << N << " random values." << endl; std::vector<int> bigv; generate_n(back_inserter(bigv), N, rand); // sort the array cout << "Sorting array of " << N << " random values." << endl; std::sort(bigv.begin(), bigv.end()); cout << "Running " << N << " identity searches..." << endl; for (int i=1;i<N; i++) if (!inRange(bigv[i-1],bigv[i],&bigv[0],N)) { cout << "Error: could not find value in range [" << bigv[i-1] << ',' << bigv[i] << "]" << endl; break; }; cout << "Finished" << endl; return 0; } Output Results: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 Sorting array of 2000000 random values. Running 2000000 identity searches... Finished
It's actually pretty straight forward if you assume the array to be sorted. You can get away with logarithmic complexity by always looking at either the respective left or right side of the sequence: #include <iterator> template <typename Limit, typename Iterator> bool inRange(Limit lowerBound, Limit upperBound, Iterator begin, Iterator end) { if (begin == end) // no values => no valid values return false; Iterator mid = begin; auto const dist = std::distance(begin,end); std::advance(mid,dist/2); // mid might be equal to begin, if dist == 1 if (lowerBound < *mid && *mid < upperBound) return true; if (dist == 1) // if mid is invalid and there is only mid, there is no value return false; if (*mid > upperBound) return inRange(lowerBound, upperBound, begin, mid); std::advance(mid,1); // we already know mid is invalid return inRange(lowerBound, upperBound, mid, end); } You can invoke this for plain arrays with: inRange(2,25,std::begin(A),std::end(A));
To my understanding, using divide and conquer for your specific problem will not yield an andvantage. However, at least in your example, the input is sorted; is should be possible to improve a bit by skipping values until your lower bound is reached.