0

Let me start by saying that I am only perhaps at an intermediate level in coding, but am not too familiar with DS and Algo.

I wrote this bit of code that returns the sum of a given number of elements from an array above a certain value, where :

h : height(or value of each item/element)

k : value that the sum needs to be greater than

n_o : length of the original array, that I reduce during recursion.

n_a : length of my answer array(the array which stores the combination of elements whose sum is to be considered), which I increase during recursion.

l : the number of elements whose sum is to be considered.

ans : my answer array.

sum(int array[], int length_of_array) : a function I defined that finds the sum of an array, given its length.

void solve(int h[], int k, int n_o, int n_a, int l, int ans[] = {}){
    if(n_a == l){ // base case, if number of elements considered = length of ans array
        int s = sum(ans, n_a); // finds sum of ans[]
        if(s > k){ // checks if sum > defined value
            cout << s;
        }
        cout << endl;
        return;
    }

    for(int i = 0; i < n_o; i++){ // loops through all elements in curent h[]
        int newAns[n_a+1]; // creates a new array which stores the previous ans[] + a new element from h[]
        for(int j = 0; j < n_a; j++){
            newAns[j] = ans[j];
        }
        newAns[n_a] = h[i];
        //ros stands for rest of string.
        int ros[n_o-i-1]; // creates a new array which stores the new h[] to be passed on.
        for(int j = i+1; j < n_o; j++){
            ros[j-i-1] = h[j];
        }
        solve(ros, k, n_o-i-1, n_a +1, l, newAns);//recursively calls the function.
    }
}

my input is :

k = 38

h[] = 20 19 10 8 8 7 7 7

This code runs just fine, but it goes through all possible cases and calculates all possible sums, but only prints those above the defined value(k). This Code executes on roughly 1.8s on VSCode.

now my thought process was that I can make this more efficient by reducing the number of recursions, by simply running a check of if it is even possible to reach the sum after some elements. For eg, for l=2(only 2 elements can be considered) once you have considered 20, 19, no other element can reach the sum, and then once you have considered 20, and start from 19, no combination of 2 elements reach 38.

so then I updated the code to this,

void solve(int h[], int k, int n_o, int n_a, int l, int ans[] = {}){
    if(n_a == l){
        int s = sum(ans, n_a);
        if(s > k){
            cout << s;
        }
        cout << endl;
        return;
    }

    for(int i = 0; i < n_o; i++){
        //This is the new part.
        int s = 0;
        for(int x = i; x < l-n_a; x++){
            s += h[x];
        }
        if(sum(ans, n_a) + s < k){
            return;
        }
        //upto here
        int newAns[n_a+1];
        for(int j = 0; j < n_a; j++){
            newAns[j] = ans[j];
        }
        newAns[n_a] = h[i];
        int ros[n_o-i-1];
        for(int j = i+1; j < n_o; j++){
            ros[j-i-1] = h[j];
        }
        solve(ros, k, n_o-i-1, n_a +1, l, newAns);
    }
}

This new bit of code just checks if the sum of the remaining number of elements to be considered(l - n_a) + the sum of the existing ans[] gives a value greater than k or not, and returns if not.

Although imo this should have greatly reduced the time of execution, the program now actually takes more time to execute( between 1.8s and 2.5s on VSCode).

Can someone please explain why or where I went wrong? Also, if possible, how I can improve this code.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 1
    Did you try running it with a profiler? I would consider not to calculate the sum over and over again but to pass it along with ans to solve, then calculating the sum is just taking the old sum plus the added value. – Werner Henze Jan 11 '21 at 20:42
  • @WernerHenze I dont know what a profiler is. And if you mean passing the sum during recursion, it would take lesser time, but currently i am more interested in why the extra code i wrote didnot reduce the execution time – Akash Chattopadhyay Jan 12 '21 at 08:50
  • A profiler is a program that starts your program, monitors it and checks where it consumes time. My guess would be that the additional loop and the additional call to sum cost more than they give you benefit. Maybe the sum is calculated very often but the return is almost never done. Thus my hint to reduce the time needed for the sum by calculating it on the fly and not every time over and over again. – Werner Henze Jan 12 '21 at 09:42
  • @WernerHenze ahh ok thank you I will change the code to pass sum during recursion and then then try running it through a profiler and see where it going wrong – Akash Chattopadhyay Jan 19 '21 at 05:12

0 Answers0