Reputation: 51
Here is the function that i have written.
public static boolean existsSum(int[] arr, int n, int sum){
if(sum==0)
return true;
if(n<=0)
return false;
if(arr[n-1] == sum)
return true;
if(sum<0)
return false;
if(sum<arr[n-1])
return existsSum(arr, n-1,sum);
return existsSum(arr, n-1, sum-arr[n-1]) || existsSum(arr, n-1,sum) ;
}
This works perfectly fine. But as soon as I change last line of code like this
public static boolean existsSum(int[] arr, int n, int sum){
if(sum==0)
return true;
if(n<=0)
return false;
if(arr[n-1] == sum)
return true;
if(sum<0)
return false;
if(sum<arr[n-1])
return existsSum(arr, n-1,sum);
return existsSum(arr, n-1,sum) || existsSum(arr, n-1, sum-arr[n-1]) ;
}
It exceeds the time limit. I can't understand what is the impact on execution time upon changing the sequence. Please help.
Upvotes: 3
Views: 677
Reputation: 1760
This should be O(n)
public static boolean sumExists(int [] in, int sum) {
//You might be able to get away with just sorting the values and not copying it.
int [] input = Arrays.copyOf(in, in.length);
Arrays.sort(input);
int currentSum = 0;
int startIdx = 0;
for (int i = 0; i < input.length; i++) {
if (currentSum > sum) {
while (currentSum > sum && startIdx < i) {
currentSum -= input[startIdx++];
}
}
if (currentSum == sum) {
return true;
}
currentSum += input[i];
}
return false;
}
Upvotes: 0
Reputation: 271625
Note the fact that ||
is short-circuiting i.e. in a || b
, if a
is true, b
is not evaluated.
The difference between the two operands of ||
is that existsSum(arr, n-1, sum-arr[n-1])
"adds" the current item to the list of items that sums to the total sum, while existsSum(arr, n-1, sum)
doesn't.
In the first code snippet, if existsSum(arr, n-1, sum-arr[n-1])
is true, existsSum(arr, n-1, sum)
is not even called. Imagine I call this with the array [1,2,3]
and the sum 6. The first operand is going to return true every recursive call, and there is no need to evaluate the second operand.
Similarly, in the second code snippet, existsSum(arr, n-1, sum)
is run first, and if true, existsSum(arr, n-1, sum-arr[n-1])
is not called. However, existsSum(arr, n-1, sum)
can rarely return true on its own. What I mean by this is that for the call existsSum(arr, n-1, sum)
to return true, the value true
must have come from a recursive call to existsSum(arr, n-1, sum-arr[n-1])
. You can verify this by analysing the different branches. (the two branches that return true are sum==0
and arr[n-1] == sum
. Hopefully you'll agree both are rare) This means that backtracking (i.e. calling existsSum(arr, n-1, sum-arr[n-1])
) will definitely happen for existsSum(arr, n-1, sum)
.
In the worst case though, these two code snippets are the same.
Upvotes: 4