Is is possible to find the largest sum contiguous sub array using recursion such that the function would directly return the output.
Below is my solution where I store the max subarray ending at each index and then find the largest among those in the print() function. However, I want the following
Use recursion
Use the recursive function to directly output the final result.
My code which uses a recursive function and a helper print() function to find the largest among those numbers
#include <stdio.h>
//int a[] = {-6,60,-10,20};
int a[] = {-2, -3, 4, -1, -2, 1, 5, -3};
int len = sizeof(a)/sizeof(*a);
int maxherearray[10];
int main(void)
{
fun(len-1);
printf("max sub array == %d\n",print(maxherearray));
printf("\n");
return 0;
}
int fun(int n)
{
if(n==0)
return a[n];
maxherearray[n] = max(a[n], a[n]+fun(n-1));
return maxherearray[n];
}
int max(int a, int b)
{
return (a > b)? a : b;
}
EDIT : Posting the print() function which I somehow missed out
//Please make sure that #include <limits.h> is added
int print(int a[])
{
int i = 0;
int largest = INT_MIN;
printf("largest == %d\n",largest);
for(i=0;i<len;i++)
{
if(a[i] > largest)
largest = a[i];
}
return largest;
}
Generally, your algorithm logic is OK. It's like,
f(0) = a(i);
f(i) = max(f(i-1) + a(i), a(i));, get the middle result array
max(0, f(1), f(2), ... , f(n-1)), get the final max_sub result
And you designed a function namedfun for #2, and a helper print() for #3.
Now, (I guess ) what you'd like is to combine #2 and #3 together, i.e., to utilise the middle results of #2 to avoid extra computing/memory space. In terms of your original algorithm logic, here are some possible ways, such as
Add a parameter in your fun to keep max_sub result
int fun(int n, int *result)// add int *result to return max_sub
{
int max_here = 0;
if(n==0){
return a[n];
}
max_here = max(a[n],a[n]+fun(n-1, result));
*result = max(*result, max_here);
return max_here;
}
//...
int main(void)
{
int result = 0;
fun(len-1, &result);
printf("max sub : %d\n", result);
}
Use a global variable (Oh!) to get max_sub in time
int g_maxhere = 0;
int fun2(int n)
{
if(n==0){
return a[n];
}
g_maxhere = max(g_maxhere, max(a[n],a[n]+fun2(n-1)));
return max(a[n], a[n]+fun2(n-1));
}
//...
int main(void)
{
fun2(len-1);
printf("max sub:%d\n",g_maxhere)
}
In fact, your original solution of using a helper function can make your algorithm more clear.
Introduce two global variables, start_idx and end_idx to track the start and end indices of the largest contiguous subarray. Update these variables accordingly in the recursive function.
#include <stdio.h>
/* int a[] = {-6,60,-10,20}; */
int a[] = {-2, -3, 4, -1, -2, 1, 5, -3};
int len = sizeof(a)/sizeof(*a);
int maxherearray[10];
int fun(int n);
int max(int a, int b);
int find_max(int a[], int len);
void print_array(int a[], int start_idx, int end_idx);
int start_idx = 0; // Start of contiguous subarray giving max sum
int end_idx = 0; // End of contiguous subarray giving max sum
#define NEG_INF (-100000)
int max_sum = NEG_INF; // The max cont sum seen so far.
int main(void)
{
start_idx = 0;
end_idx = len - 1;
maxherearray[0] = a[0];
printf("Array a[]: ");
print_array(a, 0, len-1);
printf("\n");
// Compute the necessary information to get max contiguous subarray
fun(len - 1);
printf("Max subarray value == %d\n", find_max(maxherearray, len));
printf("\n");
printf("Contiguous sums: ");
print_array(maxherearray, 0, len - 1);
printf("\n");
printf("Contiguous subarray giving max sum: ");
print_array(a, start_idx, end_idx);
printf("\n\n");
return 0;
}
int fun(int n)
{
if(n==0)
return a[0];
int max_till_j = fun(n - 1);
// Start of new contiguous sum
if (a[n] > a[n] + max_till_j)
{
maxherearray[n] = a[n];
if (maxherearray[n] > max_sum)
{
start_idx = end_idx = n;
max_sum = maxherearray[n];
}
}
// Add to current contiguous sum
else
{
maxherearray[n] = a[n] + max_till_j;
if (maxherearray[n] > max_sum)
{
end_idx = n;
max_sum = maxherearray[n];
}
}
return maxherearray[n];
}
int max(int a, int b)
{
return (a > b)? a : b;
}
// Print subarray a[i] to a[j], inclusive of end points.
void print_array(int a[], int i, int j)
{
for (; i <= j; ++i) {
printf("%d ", a[i]);
}
}
int find_max(int a[], int len)
{
int i;
int max_val = NEG_INF;
for (i = 0; i < len; ++i)
{
if (a[i] > max_val)
{
max_val = a[i];
}
}
return max_val;
}
Related
I am solving algorithm problem.
It is elements in array, pair -> one value;
I input array's size and add value.
i solve this problem but i meet time complexity problem at biggggg number - n
how can i solve this time complexity problem?
i try to solve one for loop but can't well
plz help me
#include <stdio.h>
int main(void){
int n,m,i,j;
int count=0;
scanf("%d %d",&n, &m);
int array[n];
for(i=0;i<n;i++){
scanf("%d",&array[i]);
}
for(i=0;i<n;i++){
for(j=i;j<n;j++){
if(m==array[i]+array[j]){
count++;
}}
}
printf("%d",count);
return 0;
}
Here is a simple two-pointer technique, after sorting.
It will work as it is because there is no duplicate.
In practice, two indices are used, one from the start of the array, one from the end of the array. We increase the first or decrease the second one, depending on the value of the sum.
Complexity: O(n logn) for sorting, and O(n) for the second step.
#include <stdio.h>
#include <stdlib.h>
int compare_ints(const void* a, const void* b)
{
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
int count_sum (int* A, int n, int target) {
int count = 0;
qsort(A, n, sizeof(int), compare_ints);
int left = 0;
int right = n-1;
while (left < right) {
int sum = A[left] + A[right];
if (sum == target) {
count++;
left++;
right--;
} else if (sum < target) {
left++;
} else {
right--;
}
}
return count;
}
int main() {
int A[] = {8, 2, 7, 5, 3, 1};
int target = 10;
int n = sizeof(A)/sizeof(A[0]);
int ans = count_sum (A, n, target);
printf ("count = %d\n", ans);
return 0;
}
according to introduction to algorithms I wrote a code for quicksort using Hoare's partition in the codeblocks IDE .The code was successfully built but the sorted array is not displayed on the console,only the unsorted array is displayed followed by a blinking underscore.
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
int partition(int arr[],int p,int r)
{
int i,j,x,temp;
x=arr[p];
i=p-1;
j=r+1;
while(true)
{
do{
j=j-1;
}while(arr[j]<=x);
do{
i=i+1;
}while(arr[i]>=x);
if (i<j)
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
else
return j;
}
}
void quicksort(int arr[],int p,int r)
{
if (p<r)
{
int q=partition(arr,p,r);
quicksort(arr,p,q-1);
quicksort(arr,q-1,r);
}
}
void print(int A[],int size)
{
int i;
for(i=0;i<size;i++)
printf("%d ",A[i]);
}
int main()
{
int arr[]={1,12,56,2,67,0,98,23};
int size=sizeof(arr)/sizeof(arr[0]);
printf("\nthe array is\n");
print(arr,size);
quicksort(arr,0,size-1);
printf("\nthe sorted array is\n ");
print(arr,size);
return 0;
}
the output was as follows
the array is
1 12 56 2 67 0 98 23
`
Okay, I refactored your algorithm, based on a guide from wikipedia: https://en.wikipedia.org/wiki/Quicksort
As mentioned in my comment above, the [recursive] quicksort calls used the wrong arguments. But, then, as Weather Vane mentioned, it [still] didn't sort.
Edit: My original post was using Lomuto partitioning instead of Hoare.
The partition algorithm differed from the wiki by using a different initial value for the pivot and using <=,>= on the do/while termination conditions instead of <,>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int
partition(int arr[], int p, int r)
{
int i,
j,
x,
temp;
x = arr[(p + r) / 2];
i = p - 1;
j = r + 1;
while (1) {
do {
i += 1;
} while (arr[i] < x);
do {
j -= 1;
} while (arr[j] > x);
if (i >= j)
return j;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
void
quicksort(int arr[], int p, int r)
{
if (p < r) {
int q = partition(arr, p, r);
quicksort(arr, p, q);
quicksort(arr, q + 1, r);
}
}
void
print(int A[], int size)
{
int i;
for (i = 0; i < size; i++)
printf("%d ", A[i]);
}
int
main()
{
int arr[] = { 1, 12, 56, 2, 67, 0, 98, 23 };
int size = sizeof(arr) / sizeof(arr[0]);
printf("\nthe array is\n");
print(arr, size);
quicksort(arr, 0, size - 1);
printf("\nthe sorted array is\n ");
print(arr, size);
printf("\n");
return 0;
}
Hi i wanted to tranform this code into a recursive function:
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
for(int j = i; j < length; j++) {
sum += a[j];
}
}
return sum;
}
My approach is :
int rec_help(int*a, int length);
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
else{
return rec_help(a,length) + rec_help(a+1,length-1) ;
}
}
int rec_help(int*a, int length){
if(a == 0 || length <= 0) return 0;
else{
int tmp = a[0];
return tmp + a3(a+1,length-1);
}
}
But i'm not getting it right.
With a3() i wanted to simulate the first for loop, and i think there is my problem :D
And with rec_help() the second loop and the body, but im mixing things here.
I would appreciate any kind of help :)
Because you have 2 loop, if you want your function to be recursive, you will need 2 recursive functions, one which will do the job of the first loop and a second to do the job of your second loop...
Something like that should work :
int a3_rec(int *a, int length)
{
if (length == 0)
return (0);
return (*a + a3_rec(a + 1, length - 1));
}
int a3_rec_hat(int *a, int length)
{
if (a == 0 || length == 0)
return (0);
return (a3_rec(a, length) + a3_rec_hat(a + 1, length - 1));
}
I hope I've helped you :)
As a general rule, when you transform loops into recursion, every loop becomes a function and any non-local variables it uses become arguments.
Your original code is
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
for(int j = i; j < length; j++) {
sum += a[j];
}
}
return sum;
}
Let's start with the innermost loop. It uses j, i, length, sum, and a from the surrounding scope.
void a3_loop0(int *pj, int length, int *psum, int *a) {
if (*pj < length) {
*psum += a[*pjj];
(*pj)++;
a3_loop0(pj, length, psum, a);
}
}
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
int j = i;
a3_loop0(&j, length, &sum, a);
}
return sum;
}
This is a very literal and mechanical translation. Every mutable variable has become a pointer (in C++ you'd use references for this), which leads to somewhat ugly and non-functional code (well, code that doesn't use idiomatic functional style). But it works, and we can proceed to the next loop in the same way:
void a3_loop0(int *pj, int length, int *psum, int *a) {
if (*pj < length) {
*psum += a[*pj];
(*pj)++;
a3_loop0(pj, length, psum, a);
}
}
void a3_loop1(int *pi, int length, int *psum, int *a) {
if (*pi < length) {
int j = *pi;
a3_loop0(&j, length, psum, a);
(*pi)++;
a3_loop1(pi, length, psum, a);
}
}
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
int i = 0;
a3_loop1(&i, length, &sum, a);
return sum;
}
Technically we're done now, but there's a number of things we can clean up.
The first thing I'd do is to change the type of a to const int * because a3 never modifies any of its elements.
The second thing I'd do is to hoist the loop variables *pi / *pj into their functions; they don't really need to be pointers to mutable objects elsewhere.
void a3_loop0(int j, int length, int *psum, const int *a) {
if (j < length) {
*psum += a[j];
a3_loop0(j + 1, length, psum, a);
}
}
void a3_loop1(int i, int length, int *psum, const int *a) {
if (i < length) {
a3_loop0(i, length, psum, a);
a3_loop1(i + 1, length, psum, a);
}
}
int a3(const int *a, int length) {
if (a == 0 || length <= 0) return 0;
int sum = 0;
a3_loop1(0, length, &sum, a);
return sum;
}
This already simplifies and shortens the code a bit.
The next step is to actually return something from these helper functions. Currently they use *psum as an accumulator and return void. We can keep the use of an accumulator but return the result directly (instead of through an output parameter) as follows:
void a3_loop0(int j, int length, int sum, const int *a) {
if (j < length) {
return a3_loop0(j + 1, length, sum + a[j], a);
}
return sum; // this was implicit before; "return sum unchanged"
}
void a3_loop1(int i, int length, int sum, const int *a) {
if (i < length) {
return a3_loop1(i + 1, length, a3_loop0(i, length, sum, a), a);
}
return sum; // ditto
}
int a3(const int *a, int length) {
if (a == 0 || length <= 0) return 0;
return a3_loop1(0, length, 0, a);
}
This version of the code is "purely functional" in that it never modifies any variables; it only passes and returns values to and from functions, respectively.
If we wanted to, we could get rid of all if statements and write everything as expressions:
void a3_loop0(int j, int length, int sum, const int *a) {
return j < length
? a3_loop0(j + 1, length, sum + a[j], a)
: sum;
}
void a3_loop1(int i, int length, int sum, const int *a) {
return i < length
? a3_loop1(i + 1, length, a3_loop0(i, length, sum, a), a)
: sum;
}
int a3(const int *a, int length) {
return a == 0 || length <= 0
? 0
: a3_loop1(0, length, 0, a);
}
I'll post this because I see the other answers use 1 function per loop which isn't necessary.
You can have just 1 recursive function:
int a3_impl(int* a, int length, int i, int j)
{
if (i >= length)
return 0;
if (j >= length)
return a3_impl(a, length, i + 1, i + 1);
return a[j] + a3_impl(a, length, i, j + 1);
}
int a3(int* a, int length)
{
if(a == 0 || length <= 0)
return 0;
return a3_impl(a, length, 0, 0);
}
can you help me with code which returns partial sum of 'X' numbers in array in c?
Complete :
int arr_sum( int arr[], int n )//Recursive sum of array
{
if (n < 0) //base case:
{
return arr[0];
}
else
{
return arr[n] + arr_sum(arr, n-1);
}
}
void sum_till_last (int *ar,int si )
{
**int sum,i;// the problem some where here
ar=(int*) malloc(si*sizeof(int));
for (i=0; i<si;i++)
{
sum=arr_sum(ar,i);
ar [i]=sum;
}
free (ar);**
}
void main ()
{
int i;
int a [5];
for (i = 0; i < 5; i++)
scanf_s("%d", &a[i]);
sum_till_last(a,5);
printf("%d\n",a[5]);
}
\i want to create new array with this this legality:
My input :
4
13
23
21
11
The output should be (without brackets or commas):
4
17
40
61
72
Now when we can see the full code, it's quite obvious that the problem is in the sum_till_last function where you overwrite the pointer you pass to the function with some new and uninitialized memory you allocate.
Drop the allocation (and the call to free of course). And fix the logical bug in arr_sum that causes you to get arr[0] + arr[0] when i is zero.
Here you go:
#include <stdio.h>
int main () {
int in_arr[5] = {4,13,23,21,11};
int out_arr[5];
int p_sum =0;
int i;
for ( i=0;i<5;i++){
out_arr[i] = in_arr[i]+p_sum;
p_sum=p_sum+in_arr[i];
}
for (i=0;i<5;i++){
printf("%d", out_arr[i] );
}
}
Fix according to your policy
#include <stdio.h>
#include <stdlib.h>
int arr_sum(int arr[], int n){
if (n == 0){//Change to this
return arr[0];
} else {
return arr[n] + arr_sum(arr, n-1);
}
}
void sum_till_last(int *ar, int si){
int sum,i;
int *temp = malloc(si * sizeof(int));//variable name ar is shadowing parameter name ar.
for(i = 0; i < si; i++){
temp[i] = arr_sum(ar, i);
if(i)
putchar(' ');
printf("%d", temp[i]);//need print out :D
}
free(temp);
}
int main(void){
int i, a[5];
for (i = 0; i < 5; i++)
scanf_s("%d", &a[i]);
sum_till_last(a, 5);
//printf("%d\n",a[5]);<-- this print only one element. and It's out of bounds element XD
}
I just made it simple so it´s easy to understand :)
I´m assuming "n" is always equal or less then array element number. Then you just print the SUM.
#include <stdio.h>
int arr_sum( int arr[], int n ){
int i=0,SUM=0;
for(; i < n;i++){
SUM= SUM+ arr[i];
printf("%d ",SUM);
}
}
int main(void) {
int array[] = {4, 13, 23, 21, 11};
arr_sum(array,5);
return 0;
}
Hey i am trying to print largest element in an array using function and pointers. Below is my code but its printing garbage value. Please help.
void findmax(int arr[],int,int*);
void findMax(int arr[], int n, int* pToMax)
{
if (n <= 0)
return; // no items, no maximum!
int max = arr[0];
pToMax = &arr[0];
for (int i = 1; i < n; i++)
{
if (arr[i] > max)
{
max = arr[i];
pToMax = (arr+i);
}
}
}
int main()
{
int nums[4] = { 5, 3, 15, 6 };
int *ptr;
findMax(nums, 4, ptr);
printf("The maximum is at address %u\n", ptr);
printf("It's at index %d\n",ptr - nums);
printf("Its value is %d\n", *ptr);
}
With int *pToMax in findMax(int arr[], int n, int* pToMax) and
calling as findMax(nums, 4, ptr); you just pass ptr as a value.
The updated value won't be reflected after function exits.
You need to use **pToMax
to save address.
void findMax(int arr[], int n, int** pToMax)
{
if (n <= 0)
return; // no items, no maximum!
int max = arr[0];
*pToMax = &arr[0]; //Store base address
for (int i = 1; i < n; i++)
{
if (arr[i] > max)
{
max = arr[i];
*pToMax = (arr+i); //Store max address
}
}
}
call using
findMax(nums, 4, &ptr);