Related
I'm trying to solve this coding problem:
Given an array of unsorted numbers and a target number, find a triplet in the array whose sum is as close to the target number as possible, return the sum of the triplet. If there are more than one such triplet, return the sum of the triplet with the smallest sum. I have a question about a portion of the solution and I've elaborated more on it further below, after the entire answer to the coding question directly below this pargraph. Entire solution:
class TripletSumCloseToTarget {
public static int searchTriplet(int[] arr, int targetSum) {
if (arr == null || arr.length < 3)
throw new IllegalArgumentException();
Arrays.sort(arr);
int smallestDifference = Integer.MAX_VALUE;
for (int i = 0; i < arr.length - 2; i++) {
int left = i + 1, right = arr.length - 1;
while (left < right) {
// comparing the sum of three numbers to the 'targetSum' can cause overflow
// so, we will try to find a target difference
int targetDiff = targetSum - arr[i] - arr[left] - arr[right];
if (targetDiff == 0) // we've found a triplet with an exact sum
return targetSum; // return sum of all the numbers
// the second part of the above 'if' is to handle the smallest sum when we have
// more than one solution
if (Math.abs(targetDiff) < Math.abs(smallestDifference)
|| (Math.abs(targetDiff) == Math.abs(smallestDifference)
&& targetDiff > smallestDifference))
smallestDifference = targetDiff; // save the closest and the biggest difference
if (targetDiff > 0)
left++; // we need a triplet with a bigger sum
else
right--; // we need a triplet with a smaller sum
}
}
return targetSum - smallestDifference;
}
public static void main(String[] args) {
System.out.println(
TripletSumCloseToTarget.searchTriplet(new int[] { -2, 0, 1, 2 }, 2));
System.out.println(
TripletSumCloseToTarget.searchTriplet(new int[] { -3, -1, 1, 2 }, 1));
System.out.println(
TripletSumCloseToTarget.searchTriplet(new int[] { 1, 0, 1, 1 }, 100));
System.out.println(
TripletSumCloseToTarget.searchTriplet(new int[] { 0, 0, 1, 1, 2, 6 }, 5));
}
}
From the above code, this portion is used to continuously check for the lowest sum to obtain the smallest solution.
// the second part of the above 'if' is to handle the smallest sum when we have
// more than one solution
if (Math.abs(targetDiff) < Math.abs(smallestDifference)
|| (Math.abs(targetDiff) == Math.abs(smallestDifference)
&& targetDiff > smallestDifference))
smallestDifference = targetDiff; // save the closest and the biggest difference
However, I'm unsure in what cases the below portion would be needed. Aren't we checking for the lowest difference? Why check if the current difference is more than a smallest difference? Shouldn't making sure the current difference is less than the smallest difference suffice?
&& targetDiff > smallestDifference)
Would really appreciate some insight regarding this portion of the solution. Thanks!!
Official answer (from original question creator):
(+ve case):
This problem is asking to find a triplet with two conditions. 1) Closest to the target 2) If there are more than one such triplet, find the triplet with the smallest sum.
For example: Array [0, 0, 1, 1, 2, 6], Target = 5
We have two solutions here: (1, 1, 2) & (0, 0, 6). Both these solutions are exactly "1" away from "5". Between these two solutions, the correct answer will be (1, 1, 2) as it has sum "4" which is less than the sum of the other triplet which is "6".
Own explanation (-ve case)
Illustrating condition 2: Example when a target sum is -ve, e.g. -5, and you have two triplets a: {-1, -1, -1,} and b: {-5, -1,-1} when you calculate their difference with -5 (i.e. -5 - (sum of b or a)), triplet a will equals -2, triplet b will equal +2, modulus of both means they are exactly “2” away from “5”. Between those two solutions, the correct answer will be {-5, -1, -1} as it has a sum of -7 which is less than the sum of the other triplet which is - 3. Just ask, is the statement -7<-3? Because it’s true, triplet b which sums up to -7 is the answer.
Another way of viewing the problem
Another way is to visualize the target sum and sum of each triplet on a number line. If two triplets are at the same distance, the triplet with smaller sum i.e. sum(a)<sum(b) is the answer.
I'm trying to find a fast way to solve the subset sum problem with a few modifications, I know the exact size of the subset I need to get the target number and I also know the input array to be a range from 1 to 2000. My questions is if there is any way to improve upon the base subset sum problem solution to make it even faster when knowing these conditions as the normal solutions are too slow. Basically the only changing part is the wanted target sum.
I would preferably want it to return all the possible subsets of the given size that add up to the target value if its possible without slowing the program down too much. An example code in python or a similar language would be appriciated.
I've tried many of the solutions for the base subset sum problem but they are too slow to execute due to the size of the input array.
Knowing the size of the subset is an incredibly powerful information, because you don't have to iterate through subset size.
Given N your subset size, you could just :
Sum up the N first elements of your input array (first subset of size N)
Iterate by substracting the first element of your subarray, and adding the element next to it, which translate to looking at the next subarray
Return the subarray if the sum equals your target number
This should be O(input array size) in time and O(1) in memory, regardless of the initial array content. There is probably a more optimal solution using the range property of your initial array.
Here is an example in C++ :
void subsetSum(std::vector<int>() array, int subArraySize, int targetNumber)
{
int sum = 0;
for (int i = 0; i < subArraySize; ++i) // Initial sum
{
sum += array[i];
}
for (int i = subArraySize; i < array.size(), ++i)
{
sum -= array[subArraySize-i];
sum += array[i];
if (sum == targetNumber)
std::cout << subArraySize-i; // this print the starting position of the subarray
}
}
First find the contiguous subarray that solves this, or as close to contiguous as we can get. The center of this is going to be target/width if width is odd, or (target-1)/width, (target+1)/width if width is even.
Having found the center, add the same number of neighbors on both sides until you get to the desired width. The rightmost element of the array will need to be shifted further right in cases where there is no contiguous solution.
Ruby code:
def f(target, width)
arr = []
# put in center of array
if width % 2 == 0
arr.append target / width
arr.append target / width + 1
else
arr.append target/width
end
# repeatedly prepend next smallest integer
# and append next largest integer
while arr.length < width
arr.unshift(arr[0] - 1)
arr.append(arr[-1] + 1)
end
# increase the last element of the array to match
# the target sum. This is only necessary if there is no
# contiguous solution. Because of integer division,
# where we need to adjust it will always be to increase
# the sum of the array.
arr[-1] += target - arr.sum
return arr
end
Example run:
> f(12342, 7)
=> [1760, 1761, 1762, 1763, 1764, 1765, 1767]
Note that this code doesn't do any of the work of confirming that a solution exists in the range (1, 2000), but your code should.
So far so fast, but finding all subsets that solve this will be slow because there are many. You can find them by pushing elements to the left and right. in pairs.
Final answer will be the sum over i of: (number of ways of pushing elements to the left by a cumulative i spaces) (number of ways of pushing elements to the right by a cumulative i spaces.
To give a simple example: for a target of 13, width of 3, we start with [3,4,6].
pushes: arrays
0: [3, 4, 6]
1: [2, 4, 7], [2, 5, 6]
2: [1, 4, 8], [1, 5, 7], [2, 3, 8]
3: [1, 3, 9]
4: [1, 2, 10]
... and we're done. There will be a massive number of these, peaking (I think) when the width of the array is half the width of the range, and the initial array is centered in the range.
I have an array [a0,a1,...., an] I want to calculate the sum of the distance between every pair of the same element.
1)First element of array will always be zero.
2)Second element of array will be greater than zero.
3) No two consecutive elements can be same.
4) Size of array can be upto 10^5+1 and elements of array can be from 0 to 10^7
For example, if array is [0,2,5 ,0,5,7,0] then distance between first 0 and second 0 is 2*. distance between first 0 and third 0 is 5* and distance between second 0 and third 0 is 2*. distance between first 5 and second 5 is 1*. Hence sum of distances between same element is 2* + 5* + 2* + 1* = 10;
For this I tried to build a formula:- for every element having occurence more than 1 (0 based indexing and first element is always zero)--> sum = sum + (lastIndex - firstIndex - 1) * (NumberOfOccurence - 1)
if occurence of element is odd subtract -1 from sum else leave as it is. But this approach is not working in every case.
,,But this approach works if array is [0,5,7,0] or if array is [0,2,5,0,5,7,0,1,2,3,0]
Can you suggest another efficient approach or formula?
Edit :- This problem is not a part of any coding contest, it's just a little part of a bigger problem
My method requires space that scales with the number of possible values for elements, but has O(n) time complexity.
I've made no effort to check that the sum doesn't overflow an unsigned long, I just assume that it won't. Same for checking that any input values are in fact no more than max_val. These are details that would have to be addressed.
For each possible value, it keeps track of how much would be added to the sum if one of that element is encountered in total_distance. In instances_so_far, it keeps track of how many instances of a value have already been seen. This is how much would be added to total_distance each step. To make this more efficient, the last index at which a value was encountered is tracked, such that total_distance need only be added to when that particular value is encountered, instead of having nested loops that add every value at every step.
#include <stdio.h>
#include <stddef.h>
// const size_t max_val = 15;
const size_t max_val = 10000000;
unsigned long instances_so_far[max_val + 1] = {0};
unsigned long total_distance[max_val + 1] = {0};
unsigned long last_index_encountered[max_val + 1];
// void print_array(unsigned long *array, size_t len) {
// printf("{");
// for (size_t i = 0; i < len; ++i) {
// printf("%lu,", array[i]);
// }
// printf("}\n");
// }
unsigned long get_sum(unsigned long *array, size_t len) {
unsigned long sum = 0;
for (size_t i = 0; i < len; ++i) {
if (instances_so_far[array[i]] >= 1) {
total_distance[array[i]] += (i - last_index_encountered[array[i]]) * instances_so_far[array[i]] - 1;
}
sum += total_distance[array[i]];
instances_so_far[array[i]] += 1;
last_index_encountered[array[i]] = i;
// printf("inst ");
// print_array(instances_so_far, max_val + 1);
// printf("totd ");
// print_array(total_distance, max_val + 1);
// printf("encn ");
// print_array(last_index_encountered, max_val + 1);
// printf("sums %lu\n", sum);
// printf("\n");
}
return sum;
}
unsigned long test[] = {0,1,0,2,0,3,0,4,5,6,7,8,9,10,0};
int main(void) {
printf("%lu\n", get_sum(test, sizeof(test) / sizeof(test[0])));
return 0;
}
I've tested it with a few of the examples here, and gotten the answers I expected.
I had to use static storage for the arrays because they overflowed the stack if put there.
I've left in the commented-out code I used for debugging, it's helpful to understand what's going on, if you reduce max_val to a smaller number.
Please let me know if you find a counter-example that fails.
Here is Python 3 code for your problem. This works on all the examples given in your question and in the comments--I included the test code.
This works by looking at how each consecutive pair of repeated elements adds to the overall sum of distances. If the list has 6 elements, the pair distances are:
x x x x x x The repeated element's locations in the array
-- First, consecutive pairs
--
--
--
--
----- Now, pairs that have one element inside
-----
-----
-----
-------- Now, pairs that have two elements inside
--------
--------
----------- Now, pairs that have three elements inside
-----------
-------------- Now, pairs that have four elements inside
If we look down between each consecutive pair, we see that it adds to the overall sum of all pairs:
5 8 9 8 5
And if we look at the differences between those values we get
3 1 -1 -3
Now if we use my preferred definition of "distance" for a pairs, namely the difference of their indices, we can use those multiplicities for consecutive pairs to calculate the overall sum of distances for all pairs. But since your definition is not mine, we calculate the sum for my definition then adjust it for your definition.
This code makes one pass through the original array to get the occurrences for each element value in the array, then another pass through those distinct element values. (I used the pairwise routine to avoid another pass through the array.) That makes my algorithm O(n) in time complexity, where n is the length of the array. This is much better than the naive O(n^2). Since my code builds an array of the repeated elements, once per unique element value, this has space complexity of at worst O(n).
import collections
import itertools
def pairwise(iterable):
"""s -> (s0,s1), (s1,s2), (s2, s3), ..."""
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
def sum_distances_of_pairs(alist):
# Make a dictionary giving the indices for each element of the list.
element_ndxs = collections.defaultdict(list)
for ndx, element in enumerate(alist):
element_ndxs[element].append(ndx)
# Sum the distances of pairs for each element, using my def of distance
sum_of_all_pair_distances = 0
for element, ndx_list in element_ndxs.items():
# Filter out elements not occurring more than once and count the rest
if len(ndx_list) < 2:
continue
# Sum the distances of pairs for this element, using my def of distance
sum_of_pair_distances = 0
multiplicity = len(ndx_list) - 1
delta_multiplicity = multiplicity - 2
for ndx1, ndx2 in pairwise(ndx_list):
# Update the contribution of this consecutive pair to the sum
sum_of_pair_distances += multiplicity * (ndx2 - ndx1)
# Prepare for the next consecutive pair
multiplicity += delta_multiplicity
delta_multiplicity -= 2
# Adjust that sum of distances for the desired definition of distance
cnt_all_pairs = len(ndx_list) * (len(ndx_list) - 1) // 2
sum_of_pair_distances -= cnt_all_pairs
# Add that sum for this element into the overall sum
sum_of_all_pair_distances += sum_of_pair_distances
return sum_of_all_pair_distances
assert sum_distances_of_pairs([0, 2, 5, 0, 5, 7, 0]) == 10
assert sum_distances_of_pairs([0, 5, 7, 0]) == 2
assert sum_distances_of_pairs([0, 2, 5, 0, 5, 7, 0, 1, 2, 3, 0]) == 34
assert sum_distances_of_pairs([0, 0, 0, 0, 1, 2, 0]) == 18
assert sum_distances_of_pairs([0, 1, 0, 2, 0, 3, 4, 5, 6, 7, 8, 9, 0, 10, 0]) == 66
assert sum_distances_of_pairs([0, 1, 0, 2, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 0]) == 54
This question already has answers here:
Find the Smallest Integer Not in a List
(28 answers)
Closed 3 years ago.
I am trying to tackle this interview question: given an array of unique positive integers, find the smallest possible number to insert into it so that every integer is still unique. The algorithm should be in O(n) and the additional space complexity should be constant. Assigning values in the array to other integers is allowed.
For example, for an array [5, 3, 2, 7], output should be 1. However for [5, 3, 2, 7, 1], the answer should then be 4.
My first idea is to sort the array, then go through the array again to find where the continuous sequence breaks, but sorting needs more than O(n).
Any ideas would be appreciated!
My attempt:
The array A is assumed 1-indexed. We call an active value one that is nonzero and does not exceed n.
Scan the array until you find an active value, let A[i] = k (if you can't find one, stop);
While A[k] is active,
Move A[k] to k while clearing A[k];
Continue from i until you reach the end of the array.
After this pass, all array entries corresponding to some integer in the array are cleared.
Find the first nonzero entry, and report its index.
E.g.
[5, 3, 2, 7], clear A[3]
[5, 3, 0, 7], clear A[2]
[5, 0, 0, 7], done
The answer is 1.
E.g.
[5, 3, 2, 7, 1], clear A[5],
[5, 3, 2, 7, 0], clear A[1]
[0, 3, 2, 7, 0], clear A[3],
[0, 3, 0, 7, 0], clear A[2],
[0, 0, 0, 7, 0], done
The answer is 4.
The behavior of the first pass is linear because every number is looked at once (and immediately cleared), and i increases regularly.
The second pass is a linear search.
A= [5, 3, 2, 7, 1]
N= len(A)
print(A)
for i in range(N):
k= A[i]
while k > 0 and k <= N:
A[k-1], k = 0, A[k-1] # -1 for 0-based indexing
print(A)
[5, 3, 2, 7, 1]
[5, 3, 2, 7, 0]
[0, 3, 2, 7, 0]
[0, 3, 2, 7, 0]
[0, 3, 0, 7, 0]
[0, 0, 0, 7, 0]
[0, 0, 0, 7, 0]
Update:
Based on גלעד ברקן's idea, we can mark the array elements in a way that does not destroy the values. Then you report the index of the first unmarked.
print(A)
for a in A:
a= abs(a)
if a <= N:
A[a-1]= - A[a-1] # -1 for 0-based indexing
print(A)
[5, 3, 2, 7, 1]
[5, 3, 2, 7, -1]
[5, 3, -2, 7, -1]
[5, -3, -2, 7, -1]
[5, -3, -2, 7, -1]
[-5, -3, -2, 7, -1]
From the question description: "Assigning values in the array to other integers is allowed." This is O(n) space, not constant.
Loop over the array and multiply A[ |A[i]| - 1 ] by -1 for |A[i]| < array length. Loop a second time and output (the index + 1) for the first cell not negative or (array length + 1) if they are all marked. This takes advantage of the fact that there could not be more than (array length) unique integers in the array.
I will use 1-based indexing.
The idea is to reuse input collection and arrange to swap integer i at ith place if its current position is larger than i. This can be performed in O(n).
Then on second iteration, you find the first index i not containing i, which is again O(n).
In Smalltalk, implemented in Array (self is the array):
firstMissing
self size to: 1 by: -1 do: [:i |
[(self at: i) < i] whileTrue: [self swap: i with: (self at: i)]].
1 to: self size do: [:i |
(self at: i) = i ifFalse: [^i]].
^self size + 1
So we have two loops in O(n), but we also have another loop inside the first loop (whileTrue:). So is the first loop really O(n)?
Yes, because each element will be swapped at most once, since they will arrive at their right place. We see that the cumulated number of swap is bounded by array size, and the overall cost of first loop is at most 2*n, the total cost incuding last seatch is at most 3*n, still O(n).
You also see that we don't care to swap case of (self at: i) > i and: [(self at:i) <= self size], why? Because we are sure that there will be a smaller missing element in this case.
A small test case:
| trial |
trial := (1 to: 100100) asArray shuffled first: 100000.
self assert: trial copy firstMissing = trial sorted firstMissing.
You could do the following.
Find the maximum (m), sum of all elements (s), number of elements (n)
There are m-n elements missing, their sum is q = sum(1..m) - s - there is a closed-form solution for the sum
If you are missing only one integer, you're done - report q
If you are missing more than one (m-n), you realize that the sum of the missing integers is q, and at least one of them will be smaller than q/(m-n)
You start from the top, except you will only take into account integers smaller than q/(m-n) - this will be the new m, only elements below that maximum contribute to the new s and n. Do this until you are left with only one missing integer.
Still, this may not be linear time, I'm not sure.
EDIT: you should use the candidate plus half the input size as a pivot to reduce the constant factor here – see Daniel Schepler’s comment – but I haven’t had time to get it working in the example code yet.
This isn’t optimal – there’s a clever solution being looked for – but it’s enough to meet the criteria :)
Define the smallest possible candidate so far: 1.
If the size of the input is 0, the smallest possible candidate is a valid candidate, so return it.
Partition the input into < pivot and > pivot (with median of medians pivot, like in quicksort).
If the size of ≤ pivot is less than pivot itself, there’s a free value in there, so start over at step 2 considering only the < pivot partition.
Otherwise (when it’s = pivot), the new smallest possible candidate is the pivot + 1. Start over at step 2 considering only the > pivot partition.
I think that works…?
'use strict';
const swap = (arr, i, j) => {
[arr[i], arr[j]] = [arr[j], arr[i]];
};
// dummy pivot selection, because this part isn’t important
const selectPivot = (arr, start, end) =>
start + Math.floor(Math.random() * (end - start));
const partition = (arr, start, end) => {
let mid = selectPivot(arr, start, end);
const pivot = arr[mid];
swap(arr, mid, start);
mid = start;
for (let i = start + 1; i < end; i++) {
if (arr[i] < pivot) {
mid++;
swap(arr, i, mid);
}
}
swap(arr, mid, start);
return mid;
};
const findMissing = arr => {
let candidate = 1;
let start = 0;
let end = arr.length;
for (;;) {
if (start === end) {
return candidate;
}
const pivotIndex = partition(arr, start, end);
const pivot = arr[pivotIndex];
if (pivotIndex + 1 < pivot) {
end = pivotIndex;
} else {
//assert(pivotIndex + 1 === pivot);
candidate = pivot + 1;
start = pivotIndex + 1;
}
}
};
const createTestCase = (size, max) => {
if (max < size) {
throw new Error('size must be < max');
}
const arr = Array.from({length: max}, (_, i) => i + 1);
const expectedIndex = Math.floor(Math.random() * size);
arr.splice(expectedIndex, 1 + Math.floor(Math.random() * (max - size - 1)));
for (let i = 0; i < size; i++) {
let j = i + Math.floor(Math.random() * (size - i));
swap(arr, i, j);
}
return {
input: arr.slice(0, size),
expected: expectedIndex + 1,
};
};
for (let i = 0; i < 5; i++) {
const test = createTestCase(1000, 1024);
console.log(findMissing(test.input), test.expected);
}
The correct method I almost got on my own, but I had to search for it, and I found it here: https://www.geeksforgeeks.org/find-the-smallest-positive-number-missing-from-an-unsorted-array/
Note: This method is destructive to the original data
Nothing in the original question said you could not be destructive.
I will explain what you need to do now.
The basic "aha" here is that the first missing number must come within the first N positive numbers, where N is the length of the array.
Once you understand this and realize you can use the values in the array itself as markers, you just have one problem you need to address: Does the array have numbers less than 1 in it? If so we need to deal with them.
Dealing with 0s or negative numbers can be done in O(n) time. Get two integers, one for our current value, and one for the end of the array. As we scan through, if we find a 0 or negative number, we perform a swap using the third integer, with the final value in the array. Then we decrement our end of an array pointer. We continue until our current pointer is past the end of the array pointer.
Code example:
while (list[end] < 1) {
end--;
}
while (cur< end) {
if (n < 1) {
swap(list[cur], list[end]);
while (list[end] < 1) {
end--;
}
}
}
Now we have the end of the array, and a truncated array. From here we need to see how we can use the array itself. Since all numbers that we care about are positive, and we have a pointer to the position of how many of them there are, we can simply multiply one by -1 to mark that place as present if there was a number in the array there.
e.g. [5, 3, 2, 7, 1] when we read 3, we change it to [5, 3, -2, 7, 1]
Code example:
for (cur = 0; cur <= end; begin++) {
if (!(abs(list[cur]) > end)) {
list[abs(list[cur]) - 1] *= -1;
}
}
Now, note: You need to read the absolute value of the integer in the position because it might be changed to be negative. Also note, if an integer is greater than your end of list pointer, do not change anything as that integer will not matter.
Finally, once you have read all the positive values, iterate through them to find the first one that is currently positive. This place represents your first missing number.
Step 1: Segregate 0 and negative numbers from your list to the right. O(n)
Step 2: Using the end of list pointer iterate through the entire list marking
relevant positions negative. O(n-k)
Step 3: Scan the numbers for the position of the first non-negative number. O(n-k)
Space Complexity: The original list is not counted, I used 3 integers beyond that. So
it is O(1)
One thing I should mention is the list [5, 4, 2, 1, 3] would end up [-5, -4, -2, -1, -3] so in this case, you would choose the first number after the end position of the list, or 6 as your result.
Code example for step 3:
for (cur = 0; cur < end; cur++) {
if (list[cur] > 0) {
break;
}
}
print(cur);
use this short and sweet algorithm:
A is [5, 3, 2, 7]
1- Define B With Length = A.Length; (O(1))
2- initialize B Cells With 1; (O(n))
3- For Each Item In A:
if (B.Length <= item) then B[Item] = -1 (O(n))
4- The answer is smallest index in B such that B[index] != -1 (O(n))
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Zero sum SubArray
An array contains both positive and negative elements, find the
subarray whose sum equals 0.
This is an interview question.
Unfortunately, I cannot read the accepted answer to this question, so I am asking it again: how to find the minimal integer subarray with zero sum?
Note, this is not a "zero subset problem". The obvious brute-force solution is O(N^2) (loop over all subarrays). Can we solve it in O(N)?
This algorithm will find them all, you can easily modify it to find the minimal subarray.
Given an int[] input array, you can create an int[] tmp array where tmp[i] = tmp[i - 1] + input[i]; so that at each element of tmp will store the sum of the input up to that element.
Now if you check tmp, you'll notice that there might be values that are equal to each other. Let's say that this values are at indexes j an k with j < k, then the subarray with sum 0 will be from index j + 1 to k. NOTE: if j + 1 == k, then k is 0 and that's it! ;)
NOTE: The algorithm should consider a virtual tmp[-1] = 0;
The implementation can be done in different ways including using a HashMap as suggested by BrokenGlass but be careful with the special case in the NOTE above.
Example:
int[] input = {4, 6, 3, -9, -5, 1, 3, 0, 2}
int[] tmp = {4, 10, 13, 4, -1, 0, 3, 3, 5}
Note the value 4 in tmp at index 0 and 3 ==> sum tmp 1 to 3 = 0, length (3 - 1) + 1 = 4
Note the value 0 in tmp at index 5 ==> sum tmp 0 to 5 = 0, length (5 - 0) + 1 = 6
Note the value 3 in tmp at index 6 and 7 ==> sum tmp 7 to 7 = 0, length (7 - 7) + 1 = 1
An array contains both positive and negative elements, find the
subarray whose sum equals 0.
Yes that can be done in O(n). If the sum of the elements within a subarray equals zero that means the sum of elements up to the first element before the sub array is the same as the sum of elements up to the last element in the subarray.
Go through the array and for each element K put the sum up to K and the index K in a hashtable, if the sum up to the current element exists already check the index of that element and the current element, if the delta is lower than the minimum subarray length, update the minimum. Update the hashtable with (sum, current index K).