C - Recursion array checking - c

i would like to ask about the array recursion in C, Let say i have an array in float
float arr[] = {12.5, 5.5, 6.0, 18.0};
i want to count the number which is greater than 10, so the result should be 2. However, below is what i did
int cntArray(float arr[], int size)
{
int number = 0;
if((cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
int main()
{
float arr[] = {12.5, 5.5, 6.0, 18.0};
int result;
result = cntArray(arr, 4);
printf("The result is : %d", result);
}
But it returns 0 as result, any solutions for it? Thanks

Another example:
int cntArray(float arr[], int size) {
if (!size) return 0;
return (arr[0] > 10.0 ? 1 : 0) + cntArray(&arr[1], size - 1);
}
Edit #1 (in reply to comment):
This simply evaluate through a ternary operator (?:) if the first index of arr[] is greater than 10.0. If true, 1 will be the lvalue, otherwise will be 0. The lvalue of cntArray(&arr[1], size - 1) (which will process the next element on the array after decrementing size and if size is different than 0, which in this case will immediately return 0) will be added to the lvalue of the ternary operator. Applying this recurring logic, the aftermath will be the number of elements in the array that are greater than 10.0.

Your cntArray() function lacks a recursion base case, and also seems to hardcode the wrong value (5 instead of 10).
It should be something like:
int cntArray(const float *arr, size_t size)
{
if(size > 0)
{
/* Count the first element, then recurse. */
const int count = arr[0] >= 10.f;
return count + cntArray(arr + 1, size -1);
}
return 0;
}

Your logic is severely flawed: You don't actually check if a value in the array is larger than 10. you also always return number which will always be zero meaning the condition will always be false.

int cntArray(float arr[], int size){
int number = 0;
if((number = cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
You maybe want to change 5 to 10.

int cntArray(float arr[], int size) {
int number = 0;
if (size > 0) number = cntArray(&arr[1], size - 1);
if (arr[0] > 10) number += 1;
return number;
}

I'm not sure what does this portion of your code does.
if((cntArray(&arr[1], size - 1))>=5)
number++;
I would something like this instead:
int cntArray(float arr[], int index, int size){
if (index == size) return 0; // base case
int rest = cntArray(arr, index + 1, size); // how many elements are greater
// then 10 in rest of the array
if (arr[index] > 10)
return rest + 1;
else
return rest;
}
And call it in the main like this:
cntArray(arr, 0, 4);

Related

finding negative number closest to 0 in array (log n complexity)

I have a question: write a function that gets an ascending array of whole numbers and their size.
It is given that the array contains at least one negative number and one positive number, and I need to find the closest negative number to the number 0.
for example: [-30,-25,-18,-10,11,11,20,30]
the function will return -10.
The problem is that I need to do it in O(log n) complexity and I don't know how to do this.
I made it only with O(n).
`
int f(int* arr, int size)
{
int i;
int result = arr[0];
for (i = 1;i < size;i++)
{
if (arr[i] < 0 && result < arr[i])
result = arr[i];
else
return result;
}
return result;
}
Here is a simple C implementation of a binary search, which works in O(log n) time.
#include <stdio.h>
int find(int *arr, size_t size)
{
size_t bot = 0;
size_t top = size; // it will never be top
size_t dif;
while((dif = top - bot) > 1) {
size_t mid = bot + dif / 2;
if(arr[mid] >= 0) { // eliminate non-negatives
top = mid;
}
else {
bot = mid;
}
}
return arr[bot];
}
int main(void) {
int arr[] = { -30, -25, -18, -10, 11, 11, 20, 30 };
size_t size = sizeof arr / sizeof arr[0]; //parentheses only needed for types
printf("%d\n", find(arr, size));
}
I like to use a binary search so that the top element is never a candidate.
Program output:
-10
Here's a possible way
int f( int *n, int size )
{
int low = 0, mid, high = size-1;
while( (mid = (low+high)/2) && n[mid] * n[mid+1] > 0 ) n[mid] < 0 ? (low = mid) : (high = mid);
return n[mid] ? n[mid] : n[mid-1];
}
I posted it condensed to give you something to do. Rewrite it properly using if else and do while.
The program uses min, max and mid as indexes for the array n[].
min is set to 0 and will always be the index of a negative number, max is set to size-1 and will always be the index of a positive number or of a 0. mid will always be between them (or exactly them).
The loop breaks when find an element (that is n[mid]) such that multiplied for the next one gives a negative number or zero.
Then the function returns n[mid], unless it is 0, in this case it returns the element before n[mid].
Note that if the array can contain dupes, then you need to handle the case of multiple 0s adding something like that at the end
while( !n[mid] ) --mid;
EDIT: I forgot to tell you that since the algorithm for the function is a binary search, it suits your time complexity requirements.

Find a series with recursion

I'm trying to write a recursive function that gets an array by pointer and its size, and returns the length of the longest series of identical adjacent numbers in the array (assume that there is a series),
For example:
array: {1 2 3 3 4 5 6 6 6 6 7 8}
returns-->: 4
but I don't know what's wrong with my function; I think I got it all wrong.
Any ideas on how to fix it?
#include <stdio.h>
#include <stdlib.h>
int LongestSeries(int* arr, int size, int* count, int* maxcount);
int main()
{
int i, size, *arr, count=0, maxcount=0;
// allocation an array (unknow size)
{
printf("Enter Size of the Array-->:");
scanf("%d", &size);
arr = (int*)malloc(size * sizeof(int));
if (arr == NULL)
{
printf("Error!!");
exit(1);
}
printf("Enter Numbers for the Array:\n");
for (i = 0; i < size; i++)
{
printf("Enter a Number-->:");
scanf("%d", &arr[i]);
}
}
for (i = 0; i < size; i++)
printf(" %d ", arr[i]);
printf("\n");
printf(" %d \n", LongestSeries(arr, size, count, maxcount));
free(arr);
return 0;
}
int LongestSeries(int* arr, int size, int* count, int* maxcount)
{
if (arr[size-1] == arr[size-2])
count++;
if (maxcount<count)
maxcount = count;
LongestSeries(arr, size - 1, count, maxcount);
if (*arr==arr[0])
return maxcount;
}
There're some problems in your code:
1 - The function LongestSeries expects a pointer on count and maxcount arguments but you passed the variable's values instead. You need to change the function call to send the address reference, like this: printf(" %d \n", LongestSeries(arr, size, &count, &maxcount));
2 - Your recursion termination condition is placed below the recursion call, causing the recursion never ending. You need to place it above the recursion call, preferably be the first statement in your recursive function.
3 - Since your count and maxcount arguments are pointers, you must use the dereference operator to work with the values instead its addresses:
from this:
if (arr[size-1] == arr[size-2])
count++;
if (maxcount<count)
maxcount = count;
to this:
if (arr[size-1] == arr[size-2])
++*count;
if (*maxcount < *count)
*maxcount = *count;
4 - The same applies in your return statement: you're returing the pointer, but your function expects an int to be returned, so:
from this:
if (*arr==arr[0])
return maxcount;
to this:
if (*arr==arr[0])
return *maxcount;
5 - Since you need the longest series, your count variable needs to start at 1, not 0, since the lowest possible series in a number sequence is 1, and not 0.
Hope it helps.
There are many problems with the posted code, as pointed out by #MarcLaurent. But fundamentally, the approach seems flawed. The point of writing recursive functions is not to make things difficult, but to make things simple. Problems that lend themselves to recursion can be broken down into smaller subproblems.
For the problem at hand, finding the length of the longest sequence of repeated numbers in an array, one recursive approach would acknowledge that this length is either the length of the initial sequence of repeated numbers, or the length of the longest sequence of repeated numbers in the remainder of the array. In code, this might look like:
size_t longest_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
size_t count = init_seq(sz, a);
return MAX(count, longest_seq(sz - count, a + count));
}
Here, if the array contains no elements (the base case), 0 is returned. Otherwise, the larger of the length of the initial sequence, or the longest sequence in the remainder of the array is returned. MAX is a macro here, easily defined, and we have only to write a function that finds the length of the initial sequence. This can also be recursive, though it need not be.
A recursive function that finds the length of the initial sequence could look like:
size_t init_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
return 1 + ((sz > 1 && a[0] == a[1]) ? init_seq(sz - 1, a + 1) : 0);
}
Here, if the array contains no elements (the base case), then the length is obviously 0, otherwise the return value is 1 added to the length of the initial sequence of the remainder of the array (if there is a next element, and that element is the same as the first element), or 0.
By breaking the problem down in this way, the solution is simple and easy to understand. Here is a full program implementing the above ideas:
#include <stdio.h>
#define MAX(X, Y) (X) > (Y) ? (X) : (Y)
size_t longest_seq(size_t, int *);
size_t init_seq(size_t, int *);
int main(void)
{
size_t arr_sz;
printf("Enter number of elements: ");
scanf("%zu", &arr_sz);
int arr[arr_sz];
printf("Enter array values:\n");
for (size_t i = 0; i < arr_sz; i++) {
scanf("%d", &arr[i]);
}
printf("Longest sequence of repeats: %zu\n", longest_seq(arr_sz, arr));
return 0;
}
size_t longest_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
size_t count = init_seq(sz, a);
return MAX(count, longest_seq(sz - count, a + count));
}
size_t init_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
return 1 + ((sz > 1 && a[0] == a[1]) ? init_seq(sz - 1, a + 1) : 0);
}
Sample program interaction:
Enter number of elements: 12
Enter array values:
1 2 3 3 4 5 6 6 6 6 7 8
Longest sequence of repeats: 4
int LongestSeries(int* arr, int size, int count, int maxcount){
if(size == 0)
return maxcount < count ? count : maxcount;
if(count == 0){
return LongestSeries(arr + 1, size - 1, 1, maxcount);
} else {
if(arr[-1] == *arr){
return LongestSeries(arr + 1, size - 1, count + 1, maxcount);
} else {
if(count > maxcount)
maxcount = count;
return LongestSeries(arr + 1, size - 1, 1, maxcount);
}
}
}
int main(void){
int arr[] = {1, 2, 3, 3, 4, 5, 6, 6, 6, 6, 7, 8};
int size = sizeof(arr)/sizeof(*arr);
printf("%d\n", LongestSeries(arr, size, 0, 0));
}
reduce code:
int LongestSeries(int* arr, int size, int count, int maxcount){
if(size == 0)
return maxcount < count ? count : maxcount;
if(count == 0 || arr[-1] != *arr){
if(count > maxcount)
maxcount = count;
return LongestSeries(arr + 1, size - 1, 1, maxcount);
}
return LongestSeries(arr + 1, size - 1, count + 1, maxcount);
}

Binary Search Seg Fault

I'm trying to implement a binary search in a slightly non-traditional way by using only 3 arguments int value (what I'm looking for), int values[] (the array), int n (the size of the array). The code below finds the number 2 and recognizes that 13 is not there, but cannot find numbers like 6 or 7. I think the problem is in the final recursive call. It could be a pointer issue. I'm certain the rest of the code works fine. Any thoughts on where I might be going wrong would be appreciated.
#include <stdio.h>
#include <stdbool.h>
bool search(int value, int values[], int n);
int main(void)
{
int value = 6;
int values[] = {1, 2, 3, 4, 5, 6, 7};
int n = 7;
bool x = search(value, values, n);
if (x == true)
printf("found\n");
else
printf("not found\n");
}
bool search(int value, int values[], int n)
{
int midpoint = n/2;
if (n/2 <= 0)
{
return false;
}
if (value == values[midpoint])
{
return true;
}
if (value < values[midpoint])
{
return search(value, values, n/2);
}
else if (value > values[midpoint])
{
return search(value, values, n/2);
}
return false;
}
Yes, the problem is that when you call search with the upper half of the array, you should pass it with the offset like
return search(value, values + (n + 1) / 2, n / 2);
Note that I also skipped the middle element that you have already compared for the cases when n is odd. You can of course optimize the recursive calls, always taking care that also the length is calculated correctly.

Modify any element of the array

Given an array of integers , you can modify any of a number of arbitrary positive integer , and ultimately makes the entire array is strictly increasing and are positive integers , and asked at least need to change a few numbers
input: 5 1 2 2 3 4
output: 3
and there is what i have tried ,Each number in order to reduce more a ( first number minus one , then the second number minus two ,the third number minus three)
#include <stdio.h>
int Modify_the_array(int B[],int n);
int max(int a,int b);
int main(int argc,char *argv) {
int before_array[]={1,2,3,4,1,2,3,4,5};
int len=sizeof(before_array[0])/sizeof(before_array);
int b;
b=Modify_the_array(before_array,len);
printf("%d\n",b);
return 0;
}
int max(int a,int b){
return a>b?a:b;
}
int Modify_the_array(int B[],int len) {
int i,b=0,n=1;
int maxsofar,tmp,j;
for (i=0;i<len;i++){
B[i]=B[i]-n;
n++;
}
maxsofar=0;
tmp=0;
for(i=0;i<len;i++) {
for (j=i+1;j<len;j++) {
if (B[j]==B[i]&&B[i]>1) {
maxsofar=max(maxsofar,++tmp);
b=len-maxsofar;
}
}
}
return b;
}
somebody recommend there is another solution for this question,more efficently ,can anyone give me some advice,thank in advance
I came across the same problem recently. To make clear:
Problem Statement
You are given a sequence of integers a1,a2,a3.....an. You are free to replace any integer with any other positive integer. How many integers must be replaced to make the resulting sequence strictly increasing?
Input Format
The first line of the test case contains an integer N - the number of entries in the sequence.
The next line contains N space separated integers where the ith integer is ai.
Output Format
Output the minimal number of integers that should be replaced to make the sequence strictly increasing.
Given your input, len = 5, arr = [1 2 2 3 4], after minus index+1, get [0 0 -1 -1 -1].
Ignoring negative elements(these must be changed), compute Longest Increasing Subsequence(nondecreasing for this problem), which is a classic Dynamic Programming problem.
Denote the length of LIS = n(these elements will not be changed). So the final answer(the part doesn't belong to the increasing subsequence and the ignored negative part) is len-n(5-2=3).
We can compute LIS in O(nlogn) time with O(n) space.
int solve(vector<int> &arr) {
int len = arr.size();
for(int i = 0; i < len; i++) {
arr[i] -= i+1;
}
vector<int> lis(len,0);
int n = 0;
for(int i = 0; i < len; i++) {
if(arr[i] >= 0) {
int pos = binarysearchPos(lis,n,arr[i]);
lis[pos] = arr[i];
if(n == pos)
n++;
}
}
return len-n;
}
int binarysearchPos(vector<int> &arr, int n, int target) {
if(n == 0)
return 0;
if(arr[n-1] <= target)
return n;
int low = 0, high = n-1;
while(low < high) {
int mid = (low+high)/2;
if(arr[mid] > target) {
high = mid;
} else {
low = mid+1;
}
}
return low;
}

maximal value in recursion

I have this homework assignment:
Let Pi be the element of arr in index i. We say an index i is ‘well-placed’ if there exists an index j (j >= i) so that summing the elements in Pi Pi+1 … Pj yields the index i. In other words, an index is ‘well-placed’ if a sequence of elements beginning at that index yields the index when summed.
We define ‘well-placed length’ of a well-placed index to be j-i+1 – The length of the sequence that when summed shows that the index is well placed. It is possible an index is well-placed with more than a single sequence of elements. The ‘well-placed length’ in that case is the maximal length of the various sequences defining the index as ‘well-placed’.
The ‘maximal well-placed length’ is the maximum between the well-placement length of all well-placed indices in arr.
If no index in the array is well-placed, the maximal well-placed length is considered to be zero.
This is the code I wrote (that does not work):
int longestIndexHelper(int arr[], int i, int cur, int sum, int flag)
{
if((arr[i]==115)||(i<0))
return 0;
if((sum==0)&&(flag==0))
cur= i;
if((sum+arr[i]==cur)&&(arr[i]<=cur))
return longestIndexHelper(arr, i+1, i, sum+arr[i], 1)+1;
else return 0;
}
int longestIndex(int arr[], int length)
{
int l, h;
if(length<=0)
return 0;
l= longestIndexHelper(arr, length-1, 0, 0, 0);
h= longestIndexHelper(arr, length, 0, 0, 0);
if(h>=l)
return longestIndex(arr, length-1);
else
return longestIndex(arr, length-2);
}
I tried to understand why it doesn't return the maximal value, I assume that the IF and ELSE need to define something else to do... I'm allowed only to use these two functions.
thank you!
The problem seems to be that you need to implement two "loops" via recursion; one is a loop starting at a given index and summing the values as it goes, keeping track of the maximum well placed length for that starting index. The other is a loop trying each possible starting index. I see that your helper function does the former. It seems that you intend the called function to do the latter, but it has no mechanism to keep track of the maximum found so far or the index to check, separate from the length of the input array. To do that, you might want to create another helper function to recurse through all the possible starting indexes. Though I would approach this by expanding the existing helper function to do this also, something like:
int _helper( int arr[], int len, int start, int cur, int sum, int max )
{
if (start >= len) {
/* game over, thanks for playing */
return max;
} else if (cur >= len) {
/* try another starting index */
return _helper( arr, len, start + 1, start + 1, 0, max );
} else if ( sum + arr[cur] == start && max < cur - start + 1 ) {
/* found a longer well placed length */
return _helper( arr, len, start, cur + 1, sum + arr[cur], cur - start + 1 );
} else {
/* bzzzt. try a longer length at this starting index */
return _helper( arr, len, start, cur + 1, sum + arr[cur], max );
}
}
int max_well_placed_length( int arr[], int len )
{
return _helper( arr, len, 0, 0, 0, 0 );
}
#include <stdio.h>
int main(int argc, char **argv) {
int arr[100];
int len = 0;
if (argc > 100) return 1;
while (--argc) sscanf(*++argv, "%d", &arr[len++]);
printf("max well placed length: %d\n", max_well_placed_length(arr, len));
return 0;
}
Assume that your longestIndex function finds the 'maximal well-placed length' for a given length parameter. Then it drops it (h and l aren't stored or returned anywhere, are they?), and calls itself with a decreased length. So the function will always return the result of either longestIndex(arr, 0) or longestIndex(arr, -1) which will be always 0.
EDIT: and the longestIndexHelper function can return only 0 too.

Resources