binary search doesn't work in C - c

I have the following binary search algorithmn:
int search_binary(int* tab,int size, int a)
{
int lower=0,upper=size-1,middle=(lower + upper)/2;
while(lower < upper)
{
if(tab[middle] == a)
break;
else if(tab[middle] < a)
{
upper = middle - 1;
middle = (lower + upper)/2;
} else {
lower = middle + 1;
middle = (lower + upper)/2;
}
}
if(tab[middle] == a)
return middle;
else
return -1;
}
It either return -1 if I insert a number, that exists or it returns the wrong index.
exampledata:
table:
2
2
4
5
7
7
8
8
8
9
searched number:
7
result:
The index is: 4
table:
1
2
3
4
6
6
6
7
8
9
searched number:
4
result:
The index is: -1

else if(tab[middle] < a)
{
upper = middle - 1;
middle = (lower + upper)/2;
}
From here it seems that you expect the array to be ordered in decreasing order. In fact, giving it an array ordered that way, it works for me.
just change the if to:
if(tab[middle] > a)
To have it working for an array ordered in increasing order

A slight change in you loop in function -
int search_binary(int* tab,int size, int a)
{
int lower=0,upper=size-1,middle=(lower + upper)/2;
while(lower < upper)
{
if(tab[middle] == a){ // if found
return middle; // return index
}
else if(tab[middle] < a) // if a is greater
{
lower= middle ; //lower is updated to middle,search in part above middle
middle = (lower + upper)/2;
} else {
upper = middle - 1; //else upper is updated search in part lower than middle
middle = (lower + upper)/2;
}
}
return -1;
}
What mistake your loop was doing that when tab[middle]<a then due to updation of upper it would search number in part 0 to middle -1 whereas , number was at higher index.I have updated your code with correct changes in vairables.

Related

Find the minimum number of steps to decrease N to zero

I'm facing some difficulties in the last few days while trying to finish the following task, I hope you guys can assist :
I'm given a single number N, and I'm allowed to perform any of the two operations on N in each move :
One - If we take 2 integers where N = x * y , then we can change the value of N to the maximum between x and y.
Two - Decrease the value of N by 1.
I want to find the minimum number of steps to reduce N to zero.
This is what I have so far, I'm not sure what is the best way to implement the function to find the divisor (someFindDevisorFunction), and if this 'f' function would actually produce the required output.
int f(int n)
{
int div,firstWay,secondWay;
if(n == 0)
return 0;
div = SomefindDivisorFunction(n);
firstWay = 1 + f(n-1);
if(div != 1)
{
secondWay = 1 + f(div);
if (firstWay < secondWay)
return firstWay;
return secondWay;
}
return firstWay;
}
For example, if I enter the number 150 , the output would be :
75 - 25 - 5 - 4 - 2 - 1 - 0
I see this a recursive or iterative problem.
OP's approach hints at recursive.
A recursive solution follows:
At each step, code counts the steps of the various alternatives:
steps(n) = min(
steps(factor1_of_n) + 1,
steps(factor2_of_n) + 1,
steps(factor3_of_n) + 1,
...
steps(n-1) + 1)
The coded solution below is inefficient, but it does explore all possibilities and gets to the answer.
int solve_helper(int n, bool print) {
int best_quot = 0;
int best_quot_score = INT_MAX;
int quot;
for (int p = 2; p <= (quot = n / p); p++) {
int rem = n % p;
if (rem == 0 && quot > 1) {
int score = solve_helper(quot, false) + 1;
if (score < best_quot_score) {
best_quot_score = score;
best_quot = quot;
}
}
}
int dec_score = n > 0 ? solve_helper(n - 1, false) + 1 : 0;
if (best_quot_score < dec_score) {
if (print) {
printf("/ %d ", best_quot);
solve_helper(best_quot, true);
}
return best_quot_score;
}
if (print && n > 0) {
printf("- %d ", n - 1);
solve_helper(n - 1, true);
}
return dec_score;
}
int main() {
int n = 75;
printf("%d ", n);
solve(n, true);
printf("\n");
}
Output
75 / 25 / 5 - 4 / 2 - 1 - 0
Iterative
TBD
If you start looking for a divisor with 2, and work your way up, then the last pair of divisors you find will include the largest divisor. Alternatively you can start searching with divisor = N/2 and work down, when the first divisor found will have be largest divisor of N.
int minmoves(int n){
if(n<=3){
return n;
}
int[] dp=new int[n+1];
Arrays.fill(dp,-1);
dp[0]=0;
dp[1]=1;
dp[2]=2;
dp[3]=3;
int sqr;
for(int i=4;i<=n;i++){
sqr=(int)Math.sqrt(i);
int best=Integer.MAX_VALUE;
while(sqr >1){
if(i%sqr==0){
int fact=i/sqr;
best=Math.min(best,1+dp[fact]);
}
sqr--;
}
best=Math.min(best,1+dp[i-1]);
dp[i]=best;
}
return dp[n];
}

Binary Search - Deferred Equality check

http://ideone.com/RT84T6
while (first <= last) {
// Assert: Array is sorted and first <= last
//Initialization:target is within (extremes inclusive) the range of first and last. IE First<=x<=Last
mid = (first + last) / 2;
//Maintenance: Increasing first to mid+1 if x>mid or decrease last to min-1 if x<mid.
if (target < arr[mid])
last = mid - 1;
else
first = mid + 1;
}
//Termination: target is not within the array.
return -1;
if ((first <= target) && (arr[first]==target))
return 1;
else
return -1;
I'm getting an output of -1 each time I run my binary search (Deferred detection of equality version).
I'm having trouble figuring out where it is that its resulting in a -1.
Here's a complete solution, including a simple test driver:
#include <stdio.h>
//
// Returns the array index if target is present.
// Returns -1 if target is absent.
//
int bin_search(int *arr, int len, int target)
{
int first = 0;
int last = len - 1;
int mid;
while (first < last) {
mid = (first + last) / 2;
// Note: We require mid < last for this to work. This should be
// the case since integer division uses "truncation towards zero".
if (arr[mid] < target) {
first = mid + 1;
}
else {
last = mid;
}
}
if (first == last && arr[first] == target) {
return first;
}
return -1;
}
int main()
{
static int a[5] = {1, 2, 3, 4, 5};
int ix;
int i;
for (i = 0; i <= 6; i++) {
ix = bin_search(a, 5, i);
printf("%d: %d\n", i, ix);
}
return 0;
}
The output is:
0: -1
1: 0
2: 1
3: 2
4: 3
5: 4
6: -1
Note that I inverted the in-loop test so that last gets updated rather than first in the case where target has been found. That guarantees that last decreases in that case. The original could also be made to work, but would require the divide-by-two when setting mid to round up rather than down.
I also changed bin_search to return the index of target if present, and -1 if absent.

O(log n) algorithm to find best insert position in sorted array

I'm trying to make an algorithm that finds the best position to insert the target into the already sorted array.
The goal is to either return the position of the item if it exists in the list, else return the position it would go into to keep the list sorted.
So say I have a list:
0 1 2 3 4 5 6
---------------------------------
| 1 | 2 | 4 | 9 | 10 | 39 | 100 |
---------------------------------
And my target item is 14
It should return an index position of 5
Pseudo-code I currently have:
array = generateSomeArrayOfOrderedNumbers()
number findBestIndex(target, start, end)
mid = abs(end - start) / 2
if (mid < 2)
// Not really sure what to put here
return start + 1 // ??
if (target < array[mid])
// The target belongs on the left side of our list //
return findBestIndex(target, start, mid - 1)
else
// The target belongs on the right side of our list //
return findBestIndex(target, mid + 1, end)
I not really sure what to put at this point. I tried to take a binary search approach to this, but this is the best I could come up with after 5 rewrites or so.
There's several problems with your code:
mid = abs(end - start) / 2
This is not the middle between start and end, it's half the distance between them (rounded down to an integer). Later you use it like it was indeed a valid index:
findBestIndex(target, start, mid - 1)
Which it is not. You probably meant to use mid = (start + end) // 2 or something here.
You also miss a few indices because you skip over the mid:
return findBestIndex(target, start, mid - 1)
...
return findBestIndex(target, mid + 1, end)
Your base case must now be expressed a bit differently as well. A good candidate is the condition
if start == end
Because now you definitely know you're finished searching. Note that you also should consider the case where all the array elements are smaller than target, so you need to insert it at the end.
I don't often search binary, but if I do, this is how
Binary search is something that is surprisingly hard to get right if you've never done it before. I usually use the following pattern if I do a binary search:
lo, hi = 0, n // [lo, hi] is the search range, but hi will never be inspected.
while lo < hi:
mid = (lo + hi) // 2
if check(mid): hi = mid
else: lo = mid + 1
Under the condition that check is a monotone binary predicate (it is always false up to some point and true from that point on), after this loop, lo == hi will be the first number in the range [0..n] with check(lo) == true. check(n) is implicitely assumed to be true (that's part of the magic of this approach).
So what is a monotone predicate that is true for all indices including and after our target position and false for all positions before?
If we think about it, we want to find the first number in the array that is larger than our target, so we just plug that in and we're good to go:
lo, hi = 0, n
while lo < hi:
mid = (lo + hi) // 2
if (a[mid] > target): hi = mid
else: lo = mid + 1
return lo;
this is the code I have used:
int binarySearch( float arr[] , float x , int low , int high )
{
int mid;
while( low < high ) {
mid = ( high + low ) / 2;
if( arr[mid]== x ) {
break;
}
else if( arr[mid] > x ) {
high=mid-1;
}
else {
low= mid+1;
}
}
mid = ( high + low ) / 2;
if (x<=arr[mid])
return mid;
else
return mid+1;
}
the point is that even when low becomes equal to high you have to check.
see this example for instance:
0.5->0.75
and you are looking for true position of 0.7 or 1.
in both cases when going out of while loop: low=high=1
but one of them should be placed in position 1 and the other in position 2.
You are on the right track.
First, you do not need abs in mid = abs(end + start) / 2
Assume abs here means absolute value, because end should always be no less than start, unless there is some mistake in your code. So here abs never helps but may be potentially hiding your problem make it hard to debug.
You do not need if (mid < 2) section either , nothing special about mid smaller than two.
array = generateSomeArrayOfOrderedNumbers()
int start = 0;
int end = array.size();
int findBestIndex(target, start, end){
if (start == end){ //you already searched entire array, return the position to insert
if (stat == 0) return 0; // if it's the beginning of the array just return 0.
if(array[start] > target) return start -1; //if last searched index is bigger than target return the position before it.
else return start;
}
mid = (end - start) / 2
// find correct position
if(target == array[mid]) return mid;
if (target < array[mid])
{
// The target belongs on the left side of our list //
return findBestIndex(target, start, mid - 1)
}
else
{
// The target belongs on the right side of our list //
return findBestIndex(target, mid + 1, end)
}
}
I solved this by counting the number of elements that are strictly smaller (<) than the key to insert. The retrieved count is the insert position. Here is a ready to use implementation in Java:
int binarySearchCount(int array[], int left, int right, int key) {
if(left > right) {
return -1; // or throw exception
}
int mid = -1; //init with arbitrary value
while (left <= right) {
// Middle element
mid = (left + right) / 2;
// If the search key on the left half
if (key < array[mid]) {
right = mid - 1;
}
// If the search key on the right half
else if (key > array[mid]) {
left = mid + 1;
}
// We found the key
else {
// handle duplicates
while(mid > 0 && array[mid-1] == array[mid]) {
--mid;
}
break;
}
}
// return the number of elements that are strictly smaller (<) than the key
return key <= array[mid] ? mid : mid + 1;
}
Below is the code that is used to search a target value (which is a list of an array) from the sorted array (It contains duplicate values).
It returns the array of positions where we can insert the target values.
Hope this code helps you in any way.
Any suggestions are welcome.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int[] noDuplicateScores = IntStream.of(scores).distinct().toArray();
int[] rank = new int[alice.length];
for (int k = 0; k < alice.length; k++) {
int i=0;
int j = noDuplicateScores.length-1;
int pos=0;
int target = alice[k];
while(i<=j) {
int mid = (j+i)/2;
if(target < noDuplicateScores[mid]) {
i = mid +1;
pos = i;
}else if(target > noDuplicateScores[mid]) {
j = mid-1;
pos = j+1;
}else {
pos = mid;
break;
}
}
rank[k] = pos+1;
}
return rank;
}
Here is a solution by tweaking the binary search using python.
def func(x, y):
start = 0
end = len(x)
while start <= end:
mid = (start + end)//2
print(start, end, mid)
if mid + 1 >= len(x):
return mid + 1
if x[mid] < y and x[mid + 1] > y:
return mid + 1
elif x[mid] > y:
end = mid - 1
else:
start = mid + 1
return 0
func([1,2,4,5], 3)
Solution with slightly modified binary search in java
int findInsertionIndex(int[] arr, int t) {
int s = 0, e = arr.length - 1;
if(t < arr[s])return s;
if(t > arr[e])return e;
while (s < e){
int mid = (s + e)/2;
if(arr[mid] >= t){
e = mid - 1;
}
if(arr[mid] < t){
s = mid + 1;
}
}
return arr[s] < t? s + 1 : s;
}
The above code works upon these possible scenarios:
If arr[mid] > target -> target index lies in left half, Find the index of first max value of target and return it.
If arr[mid] < target -> target index lies in right half, Find the index of first min value of target and return the index + 1 to point the target/insertion index.
if arr[mid] == target -> Find the first occurring index of target value and return it.

Find the first element in a sorted array that is greater than the target

In a general binary search, we are looking for a value which appears in the array. Sometimes, however, we need to find the first element which is either greater or less than a target.
Here is my ugly, incomplete solution:
// Assume all elements are positive, i.e., greater than zero
int bs (int[] a, int t) {
int s = 0, e = a.length;
int firstlarge = 1 << 30;
int firstlargeindex = -1;
while (s < e) {
int m = (s + e) / 2;
if (a[m] > t) {
// how can I know a[m] is the first larger than
if(a[m] < firstlarge) {
firstlarge = a[m];
firstlargeindex = m;
}
e = m - 1;
} else if (a[m] < /* something */) {
// go to the right part
// how can i know is the first less than
}
}
}
Is there a more elegant solution for this kind of problem?
One way of thinking about this problem is to think about doing a binary search over a transformed version of the array, where the array has been modified by applying the function
f(x) = 1 if x > target
0 else
Now, the goal is to find the very first place that this function takes on the value 1. We can do that using a binary search as follows:
int low = 0, high = numElems; // numElems is the size of the array i.e arr.size()
while (low != high) {
int mid = (low + high) / 2; // Or a fancy way to avoid int overflow
if (arr[mid] <= target) {
/* This index, and everything below it, must not be the first element
* greater than what we're looking for because this element is no greater
* than the element.
*/
low = mid + 1;
}
else {
/* This element is at least as large as the element, so anything after it can't
* be the first element that's at least as large.
*/
high = mid;
}
}
/* Now, low and high both point to the element in question. */
To see that this algorithm is correct, consider each comparison being made. If we find an element that's no greater than the target element, then it and everything below it can't possibly match, so there's no need to search that region. We can recursively search the right half. If we find an element that is larger than the element in question, then anything after it must also be larger, so they can't be the first element that's bigger and so we don't need to search them. The middle element is thus the last possible place it could be.
Note that on each iteration we drop off at least half the remaining elements from consideration. If the top branch executes, then the elements in the range [low, (low + high) / 2] are all discarded, causing us to lose floor((low + high) / 2) - low + 1 >= (low + high) / 2 - low = (high - low) / 2 elements.
If the bottom branch executes, then the elements in the range [(low + high) / 2 + 1, high] are all discarded. This loses us high - floor(low + high) / 2 + 1 >= high - (low + high) / 2 = (high - low) / 2 elements.
Consequently, we'll end up finding the first element greater than the target in O(lg n) iterations of this process.
Here's a trace of the algorithm running on the array 0 0 1 1 1 1.
Initially, we have
0 0 1 1 1 1
L = 0 H = 6
So we compute mid = (0 + 6) / 2 = 3, so we inspect the element at position 3, which has value 1. Since 1 > 0, we set high = mid = 3. We now have
0 0 1
L H
We compute mid = (0 + 3) / 2 = 1, so we inspect element 1. Since this has value 0 <= 0, we set mid = low + 1 = 2. We're now left with L = 2 and H = 3:
0 0 1
L H
Now, we compute mid = (2 + 3) / 2 = 2. The element at index 2 is 1, and since 1 ≥ 0, we set H = mid = 2, at which point we stop, and indeed we're looking at the first element greater than 0.
You can use std::upper_bound if the array is sorted (assuming n is the size of array a[]):
int* p = std::upper_bound( a, a + n, x );
if( p == a + n )
std::cout << "No element greater";
else
std::cout << "The first element greater is " << *p
<< " at position " << p - a;
After many years of teaching algorithms, my approach for solving binary search problems is to set the start and the end on the elements, not outside of the array. This way I can feel what's going on and everything is under control, without feeling magic about the solution.
The key point in solving binary search problems (and many other loop-based solutions) is a set of good invariants. Choosing the right invariant makes problem-solving a cake. It took me many years to grasp the invariant concept although I had learned it first in college many years ago.
Even if you want to solve binary search problems by choosing start or end outside of the array, you can still achieve it with a proper invariant. That being said, my choice is stated above to always set a start on the first element and end on the last element of the array.
So to summarize, so far we have:
int start = 0;
int end = a.length - 1;
Now the invariant. The array right now we have is [start, end]. We don't know anything yet about the elements. All of them might be greater than the target, or all might be smaller, or some smaller and some larger. So we can't make any assumptions so far about the elements. Our goal is to find the first element greater than the target. So we choose the invariants like this:
Any element to the right of the end is greater than the target. Any
element to the left of the start is smaller than or equal to the
target.
We can easily see that our invariant is correct at the start (ie before going into any loop). All the elements to the left of the start (no elements basically) are smaller than or equal to the target, same reasoning for the end.
With this invariant, when the loop finishes, the first element after the end will be the answer (remember the invariant that the right side of the end are all greater than the target?). So answer = end + 1.
Also, we need to note that when the loop finishes, the start will be one more than the end. ie start = end + 1. So equivalently we can say start is the answer as well (invariant was that anything to the left of the start is smaller than or equal to the target, so start itself is the first element larger than the target).
So everything being said, here is the code.
public static int find(int a[], int target) {
int st = 0;
int end = a.length - 1;
while(st <= end) {
int mid = (st + end) / 2; // or elegant way of st + (end - st) / 2;
if (a[mid] <= target) {
st = mid + 1;
} else { // mid > target
end = mid - 1;
}
}
return st; // or return end + 1
}
A few extra notes about this way of solving binary search problems:
This type of solution always shrinks the size of subarrays by at least 1. This is obvious in the code. The new start or end are either +1 or -1 in the mid. I like this approach better than including the mid in both or one side, and then reason later why the algo is correct. This way it's more tangible and more error-free.
The condition for the while loop is st <= end. Not st < end. That means the smallest size that enters the while loop is an array of size 1. And that totally aligns with what we expect. In other ways of solving binary search problems, sometimes the smallest size is an array of size 2 (if st < end), and honestly I find it much easier to always address all array sizes including size 1.
So hope this clarifies the solution for this problem and many other binary search problems. Treat this solution as a way to professionally understand and solve many more binary search problems without ever wobbling whether the algorithm works for edge cases or not.
How about the following recursive approach:
public static int minElementGreaterThanOrEqualToKey(int A[], int key,
int imin, int imax) {
// Return -1 if the maximum value is less than the minimum or if the key
// is great than the maximum
if (imax < imin || key > A[imax])
return -1;
// Return the first element of the array if that element is greater than
// or equal to the key.
if (key < A[imin])
return imin;
// When the minimum and maximum values become equal, we have located the element.
if (imax == imin)
return imax;
else {
// calculate midpoint to cut set in half, avoiding integer overflow
int imid = imin + ((imax - imin) / 2);
// if key is in upper subset, then recursively search in that subset
if (A[imid] < key)
return minElementGreaterThanOrEqualToKey(A, key, imid + 1, imax);
// if key is in lower subset, then recursively search in that subset
else
return minElementGreaterThanOrEqualToKey(A, key, imin, imid);
}
}
public static int search(int target, int[] arr) {
if (arr == null || arr.length == 0)
return -1;
int lower = 0, higher = arr.length - 1, last = -1;
while (lower <= higher) {
int mid = lower + (higher - lower) / 2;
if (target == arr[mid]) {
last = mid;
lower = mid + 1;
} else if (target < arr[mid]) {
higher = mid - 1;
} else {
lower = mid + 1;
}
}
return (last > -1 && last < arr.length - 1) ? last + 1 : -1;
}
If we find target == arr[mid], then any previous element would be either less than or equal to the target. Hence, the lower boundary is set as lower=mid+1. Also, last is the last index of 'target'. Finally, we return last+1 - taking care of boundary conditions.
My implementation uses condition bottom <= top which is different from the answer by templatetypedef.
int FirstElementGreaterThan(int n, const vector<int>& values) {
int B = 0, T = values.size() - 1, M = 0;
while (B <= T) { // B strictly increases, T strictly decreases
M = B + (T - B) / 2;
if (values[M] <= n) { // all values at or before M are not the target
B = M + 1;
} else {
T = M - 1;// search for other elements before M
}
}
return T + 1;
}
Hhere is a modified binary search code in JAVA with time complexity O(logn) that :
returns index of element to be searched if element is present
returns index of next greater element if searched element is not present in array
returns -1 if an element greater than the largest element of array is searched
public static int search(int arr[],int key) {
int low=0,high=arr.length,mid=-1;
boolean flag=false;
while(low<high) {
mid=(low+high)/2;
if(arr[mid]==key) {
flag=true;
break;
} else if(arr[mid]<key) {
low=mid+1;
} else {
high=mid;
}
}
if(flag) {
return mid;
}
else {
if(low>=arr.length)
return -1;
else
return low;
//high will give next smaller
}
}
public static void main(String args[]) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
//int n=Integer.parseInt(br.readLine());
int arr[]={12,15,54,221,712};
int key=71;
System.out.println(search(arr,key));
br.close();
}
kind =0 : exact match
kind=1 : just grater than x
kind=-1 : just smaller than x;
It returns -1 if no match is found.
#include <iostream>
#include <algorithm>
using namespace std;
int g(int arr[], int l , int r, int x, int kind){
switch(kind){
case 0: // for exact match
if(arr[l] == x) return l;
else if(arr[r] == x) return r;
else return -1;
break;
case 1: // for just greater than x
if(arr[l]>=x) return l;
else if(arr[r]>=x) return r;
else return -1;
break;
case -1: // for just smaller than x
if(arr[r]<=x) return r;
else if(arr[l] <= x) return l;
else return -1;
break;
default:
cout <<"please give "kind" as 0, -1, 1 only" << ednl;
}
}
int f(int arr[], int n, int l, int r, int x, int kind){
if(l==r) return l;
if(l>r) return -1;
int m = l+(r-l)/2;
while(m>l){
if(arr[m] == x) return m;
if(arr[m] > x) r = m;
if(arr[m] < x) l = m;
m = l+(r-l)/2;
}
int pos = g(arr, l, r, x, kind);
return pos;
}
int main()
{
int arr[] = {1,2,3,5,8,14, 22, 44, 55};
int n = sizeof(arr)/sizeof(arr[0]);
sort(arr, arr+n);
int tcs;
cin >> tcs;
while(tcs--){
int l = 0, r = n-1, x = 88, kind = -1; // you can modify these values
cin >> x;
int pos = f(arr, n, l, r, x, kind);
// kind =0: exact match, kind=1: just grater than x, kind=-1: just smaller than x;
cout <<"position"<< pos << " Value ";
if(pos >= 0) cout << arr[pos];
cout << endl;
}
return 0;
}

tricky interview question in C

In the following interview question :
Given a number n, give me the numbers
(among 3..5 and an even number of
numbers) whose adding would return the
original number. The resulting numbers
should be as balanced as possible,
meaning that instead of returning 3
and 5, for instance, return 4 and
4. Ex:
7 = 3 + 4
16 = 4 + 4 + 4 + 4 rather than 3 + 5 + 4 + 4
24 = 12 + 12 or 6 + 6 + 6 + 6
I thought of the following method:
splitnumber(int n)
{
//check if the number is even
if(n%2==0)
{
print(n/2,n/2);
//check if x=2^m multiple exists or
// not..like 4,8,16 etc
print (n/x...n/x);
}
else //else if the no is odd... this part is incomplete
{
if(n-3>0)
{
print (3);
}
n-=3;
if(n>0)
{
if (n>5)
{
print(3)
n-=3;
}
}
}
}
but still I am not able to complete all the cases... How should I check when the answer has unbalanced solution??
if (n < 4) print n;
else
switch (n % 4)
case 0: *print n/4 4's*
case 1: *print n/4 - 1 4's* print 5
case 2: *print n/4 - 1 4's* print 3 print 3
case 3: *print n/4 4's* print 3
Slightly inefficient implementation in C#
if (n < 4) Console.WriteLine(n);
else
switch (n % 4)
{
case 0:
Console.WriteLine(String.Join(" ", new string('4', n / 4).ToArray()));
break;
case 1:
Console.WriteLine(
(String.Join(" ", new string('4', n/4).ToArray().Skip(1)) +
" 5").TrimStart());
break;
case 2:
Console.WriteLine(
(String.Join(" ", new string('4', n/4).ToArray().Skip(1)) +
" 3 3").TrimStart());
break;
case 3:
Console.WriteLine(String.Join(" ", new string('4', n/4).ToArray() +
" 3"));
break;
}
Here is my solution where the result will be perfectly balanced and with detection of impossible cases:
vector<int> recursive_splitnumber(int n) {
if (n <= 5) {
return vector<int>(1,n);
}
int unbalancer = 0;
vector<int> result1, result2;
do {
int val1, val2;
if (n%2 == 0) {
val1 = n%2 + unbalancer;
val2 = n%2 - unbalancer;
}
else {
val1 = (n-1)%2 + 1 + unbalancer;
val2 = (n-1)%2 - unbalancer;
}
result1 = recursive_splitnumber(val1);
result2 = recursive_splitnumber(val2);
// Concatenate the result of the even and odd splits
result1.insert(result1.end(),result2.begin(),result2.end());
++unbalancer;
} while (result1.size()%2 != 0 && unbalancer <= 1);
return result1;
}
bool splitnumber(int n) {
vector<int> split = recursive_splitnumber(n);
if (split.size()%2 == 0) {
copy(split.begin(), split.end(), ostream_iterator<int>(cout, " "));
return true;
} else
return false;
}
That solution will also take into account cases like the number 22 where the balanced division gives 11+11 (11 being a number that cannot be represented using the given rules), the subdivision will be done as 10+12, then 5+5+6+6 and finally 5+5+3+3+3+3.

Resources