Hi am trying to create a selection sort but it only appears to pass through once
the first debug displays this
3,2,10,9,5, which is correct
then the second debug displays this
2,0,0,0,0
and the last one displays this
3,0,10,9,5,
as you can see it only appears to go though the loop once instead of the 4 times that i am telling it to what am i doing wrong?
int[] List = new int[] {3, 2, 10, 9, 5};//List
int[] ListB = new int[] {0, 0, 0, 0, 0};//ListB
Debug.Log(List[0] + ","+List[1] + ","+List[2] + ","+List[3] + ","+List[4] + ",");
int minimum,temp;//2 new ints
for (int outer = 0; outer < List.Length-1; outer++)//Loop for 0 to number of ints in list -1
{
minimum = outer;//set minimum to outer
for (int inner = 0; inner < List.Length; inner++)//loop for how many ints are in the list
{
if (List[inner] < List[minimum])// if list inner < list minimum
{
minimum = inner;//set minimum to inner
}
}
ListB[outer] = List[minimum];//listb outer = list minimum
List[minimum] = 0;//set the list minimum to a dummy value
}
Debug.Log(ListB[0] + ","+ListB[1] + ","+ListB[2] + ","+ListB[3] + ","+ListB[4]);
Debug.Log(List[0] + ","+List[1] + ","+List[2] + ","+List[3] + ","+List[4] + ",");
when you set the list[minimum] to 0 the next time the loop execute will find 0 as the minimum value
you have another thing to notice, First loop should finish at list.length
this is the true code
int[] List = new int[] { 3, 2, 10, 9, 5 };//List
int[] ListB = new int[] { 0, 0, 0, 0, 0 };//ListB
Debug.log(List[0] + "," + List[1] + "," + List[2] + "," + List[3] + "," + List[4] + ",");
int minimum, temp;//2 new ints
for (int outer = 0; outer < List.Length ; outer++)//Loop for 0 to number of ints in list -1
{
minimum = outer;//set minimum to outer
for (int inner = 0; inner < List.Length; inner++)//loop for how many ints are in the list
{
if (List[inner] < List[minimum])// if list inner < list minimum
{
minimum = inner;//set minimum to inner
}
}
ListB[outer] = List[minimum];//listb outer = list minimum
List[minimum] = int.MaxValue;//set the list minimum to a dummy value
}
Debug.log(ListB[0] + "," + ListB[1] + "," + ListB[2] + "," + ListB[3] + "," + ListB[4]);
Debug.log(List[0] + "," + List[1] + "," + List[2] + "," + List[3] + "," + List[4] + ",");
Related
Here is one question from hackerrank, I have a solution but there is some testcase failed because time limit exceeded. I don't know the better solution for it.
Find Sum of elements in a subarray (if in subarray has 0, sum = sum + number x)
input:
numbers: main array(1-indexed)
queries:
array of query: left index, right index, number x(0-indexed)
output:
array of sum corresponding with queries.
my solution on C++ code:
vector<long> findSum(vector<int>numbers, vector<vector<int>> queries)
{
vector<long>result;
long sum = 0;
int count = 0;
for(auto i : queries)
{
sum = 0;
count = 0;
int l = i[0] - 1;
int r = i[1]-1;
int x = i[2];
for(int j =l; j<r;j++)
{
sum+=numbers[j]==0?x:numbers[j];
}
result.push_back(sum);
}
return result;
}
As suggested by #Annity, you need to maintain two arrays:
Sum of all numbers so far. At any point of the index, it should have the sum of all previous numbers.
Same as above but it should have the total count of all previous Zeros.
You should avoid nested loops to reduce time complexity. Here is a solution in javascript:
function findSum(numbers, queries) {
let result = [];
let subArraySum = [];
let countZero = numbers[0] == 0 ? 1 : 0;
let zeroArr = [];
zeroArr[0] = countZero;
subArraySum[0] = numbers[0];
for (let i = 1; i <= numbers.length - 1; i++) {
if (numbers[i] == 0) {
countZero++;
zeroArr[i] = countZero;
}
else {
zeroArr[i] = countZero;
}
subArraySum[i] = subArraySum[i - 1] + numbers[i];
}
for (let q of queries) {
if (q.length == 3) {
let i = q[0];
let j = q[1];
let x = q[2];
let sum = 0;
sum = subArraySum[j - 1] - ((i - 2 < 0 ) ? 0 : subArraySum[i - 2]);
sum = sum + (zeroArr[j - 1] - ((i - 2 < 0 ) ? 0 : zeroArr[i - 2])) * x;
result.push(sum);
}
}
return result;
}
console.log(findSum([5, 10, 15], [
[1, 2, 5]
]))
console.log(findSum([0, 10, 15], [
[1, 2, 5]
]))
Here's the solution that occurred to me.
You need to create two new arrays - one for the sums and one for the number of zeroes. Eg. sums[] and zeroes[].
In these two arrays you will store the value for the sum and the number of zeroes from the first element to the current. This is how it goes:
Loop through all of the numbers.
For each number with index i save in sums[i] the cumulative sum of all the elements from the first to the current and in zeroes[i] - the number of zeroes from the first element to the current.
Then loop through all of the queries.
For every query calculate the sum:
You take the sum from the sums array for the element with the right index and deduct the sum for the element before the left index.
(sum = sums[r] - sums[l-1])
If you deduct the count of zeroes in the element before the left index from the number in the element on the right index - you will get the number of zeroes in the interval.
(zero = zeroes[r] - zeroes[l-1])
Then multiply it by the third element in the query and add it to the sum.
And this is how you have the sum for the query.
this is in python
tempRes=0
temp = []
for b in range(len(queries)):
for k in range(queries[b][0]-1,queries[b][1]):
if numbers[k] == 0:
tempRes = tempRes + queries[b][2]
tempRes = tempRes + numbers[k]
temp.append(tempRes)
tempRes = 0
return temp
Your code takes a linear time per query. Invest in a linear time once to precompute an array of partial sums. Then each query will be answered in a constant time.
public static List<Long> findSum(List<Integer> numbers, List<List<Integer>> queries) {
// Write your code here
ArrayList<Long> arr = new ArrayList<>();
for(int i = 0; i < queries.size(); i++) {
int sum = 0;
for(int j = queries.get(i).get(0) - 1; j <= queries.get(i).get(1) - 1; j++) {
if(numbers.get(j) == 0){
sum += queries.get(i).get(2);
} else {
sum += numbers.get(j);
}
}
arr.add((long)sum);
sum = 0;
}
return arr;
}
The logic tries to sum each index with the last index.
But initializes the first index with 0.
The same with counting the zero.
After that, just subtract the left side with the desired index.
Also with the zero value in the index, but multiplid by the queries.
There you have it. I can't post the answer.
JS Solution:
There are two methods to solve this problem (Brute force Solution [Nested Loop]) and that's the method that responds with a timeout error throughout the execution of the test, you need to solve it with another time complexity, here is my answer 1st method O(N^2) and then 2nd method Optimized to be O(N) to solving the timeout error.
Answers in JavaScript wish it helps you.
/*
-- Brainstorming --
Have 1-indexed Array [numbers] of length n;
Have numbers of queries (q). [2D Array]
Each Query => [startIdx i, endIdx r, number x]
Find => Sum of numbers between indexes i and r (both included)
if zero occured in range add x instead of it.
*/
// 1st Method: Brute force Solution [Nested Loop]
function findSum(numbers, queries) {
const sum = new Array(queries.length).fill(0);
for (let i = 0; i < queries.length; i++) {
// let j = queries[i][0] - 1 Cause numbers 1-index not 0
for (let j = queries[i][0] - 1; j < queries[i][1]; j++) {
if (numbers[j] === 0) {
sum[i] += queries[i][2];
} else {
sum[i] += numbers[j];
}
}
}
return sum;
}
// 2nd Method: The Optimized Solution Single Loop
function findSum(numbers, queries) {
const sums = [];
const subArraySum = [];
const zerosArr = [];
let zerosCount = 0;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] === 0) {
zerosCount++;
zerosArr[i] = zerosCount;
} else {
zerosArr[i] = zerosCount;
}
subArraySum[i] = numbers[i] + (subArraySum[i - 1] || 0);
}
for (let q of queries) {
const i = q[0] - 1;
const r = q[1] - 1;
const x = q[2];
let finalSum = subArraySum[r] - (subArraySum[i - 1] || 0) + (zerosArr[r] - (zerosArr[i - 1] || 0)) * x;
sums.push(finalSum);
}
return sums;
}
console.log("1st Test: " + findSum([5,10,10], [[1,2,5]])) // 15
console.log("2nd Test: " + findSum([-5,0], [ [2, 2 ,20] , [1,2,10]])) // 20 , 5
console.log("3rd Test: " + findSum([-1,-1,1,-4,3,-3,-4], [ [1, 4 ,2]])) // -5
console.log("4th Test: " + findSum([1000000000], [[1, 1,100]]))// 1000000000
console.log("5th Test: " + findSum([-1000000000], [[1, 1,100]]))// -1000000000
Try this(in javascript):
function findSum(numbers, queries) {
// Write your code here
let sumArr = [];
for (let i = 0; i < queries.length; i++) {
let sum = 0;
let start = queries[i][0];
let end = queries[i][1] + 1;
let x = queries[i][2];
const newArr = numbers.slice(start, end);
newArr.forEach((item) => {
if (item === 0) {
sum = sum + x;
}
sum = sum + item;
});
sumArr.push(sum);
}
return sumArr;
}
#!/usr/bin/python3
def solution(numbers, queries):
if not isinstance(numbers, list) and not isinstance(queries, list):
return
result = []
total = 0
for query in queries:
if len(query) == 3:
start = query[0]
end = query[1]
additional = query[2]
selection = numbers[start-1:end]
has_zeros = False
for el in selection:
if el == 0:
has_zeros = True
print(f"has_zeros: {has_zeros}")
print(f"selection: {selection}")
total = sum(selection)
if has_zeros:
total += additional
result.append(total)
return result
if "__main__" == __name__:
# 15
_input = [5, 10, 10]
_queries = [[1], [3], [1, 2, 5]]
print(f"input: {_input}")
print(f"queries: {_queries}")
_output = solution(_input, _queries)
print(f"ouput: {_output}")
Solution in python3 :
def findSum(numbers, queries):
a = [0]
b = [0]
for x in numbers:
a.append(a[-1] + x)
b.append(b[-1] + (x == 0)) if in subarray has 0, sum = sum + number x)
return [a[r] - a[l - 1] + x * (b[r] - b[l - 1]) for l, r, x in queries]
I am trying implement a function to factoring a number, and so far I have this code:
int * factor(int n) {
int * vet;
//
int p = 2;
int index = 0;
while(n > 1) {
while(n % p != 0) {
p++;
index++;
}
n = n / p;
vet[index]++;
}
return vet;
}
this function should return a array with the powers of each prime factor of the number n. like that:
if 1200 = 2x2x2x2x3x5x5, then 1200 = 2^4 + 3^1 + 5^1, and so the function should return the array {4,1,0,3} if 1200 was the parameter.
of if 440 = 2x2x2x5x11, then 440 = x^3 + 5^1 + 11^1, and the function should return the array {3,0,0,1,0,0,0,0,0,1}
my question is about if exists some way to determine the size of vet before I start the factoration process, in the while loop.
also, with this resulting array (or with some variation of the concept above), is it possible find the powers of 2 for this number? for example:
440 = 1x2^8 + 1x2^7 + 0x2^6 + 1x2^5 + 1x2^4 + 1x2^3 + 0x2^2 + 0x2^1 + 0x2^0
resulting in the array {1,1,0,1,1,1,0,0,0}
1200 = 1x2^10 + 0x2^9 + 0x2^8 + 1x2^7 + 0x2^6 + 1x2^5 + 1x2^4 + 0x2^3 + 0x2^2 + 0x2^1 + 0x2^0
resulting in the array {1,0,0,1,0,1,1,0,0,0,0}
An easy solution which is of the quickest time:
void getFactors(int n)
{
while (n%2 == 0)
{
n = n/2;
}
for (int i = 3; i * i <= n; i = i+2)
{
// While i divides n, print i and divide n
while (n%i == 0)
{
std::cout<<i<<std::endl;
n = n/i;
}
}
}
Given an array of positive integers A, I want to find the following sum S:
S = 2^1 * (S_1) + 2^2 * (S_2) + 2^3 * (S_3) + ... + 2^n * (S_N)
where S_i is sum of product of consecutive i integers in A, for eg:
S_3 = (A[0]*A[1]*A[2]) + (A[1]*A[2]*A[3]) + .... + (A[n-3]*A[n-2]*A[n-1])
For calculating any of the S_i, I am using method similar to rolling hash, which achieve O(N):
Let tmp = A[0]*A[1]*A[2], S_3 = tmp;
For(i = 3 to n)
(tmp *= A[i]) /= A[i-3]
S_3 += tmp
And for all two's power I can precompute beforehand. So now my algorithm to calculate S is O(N^2)
My question is, is it possible to calculate S with a better complexity?
There is a recurrence pattern you could use for calculating a solution with a linear time complexity.
Consider an example input:
A = [2, 5, 3, 2, 1, 8]
Now look at the partial array with only the first element:
A0 = [2]
Call the outcome for this partial array R0. It is clear that:
R0 = 2⋅A[0] = 2⋅2 = 4
Then consider the array with one more value from the original array:
A1 = [2, 5]
Call the outcome for this partial array R1. We calculate that:
R1 = 2⋅(A[0]+A[1]) + 4⋅(A[0]⋅A[1]) = 54
We can try to write this in terms of R0, hoping we can thus limit the number of calculations to make:
R1 = 2⋅(2⋅A[0] + 1)⋅A[1] + R0
Extending again with a third element, we get:
R2 = 2⋅(A[0]+A[1]+A[2]) + 4⋅(A[0]⋅A[1] + A[1]⋅A[2]) + 8⋅(A[0]⋅A[1]⋅A[2]) = 360
Let's try to write this in terms of R1:
R2 = 2⋅(2⋅(2⋅A[0] + 1)⋅A[1] + 1)⋅A[2] + R1
There is a pattern emerging, where the first term looks much like the first term in the previous R. It is something like 2⋅(X + 1)⋅A[2], where X is the first term of the previous R. We can generally say:
Rn = 2⋅(Rn-1 − Rn-2 + 1)⋅A[n] + Rn-1
...where Rn is 0 when n < 0.
Now that is something that can be calculated in linear time. Here is an implementation in JavaScript, which also includes a second function that does the calculation in the naive, non-optimised way, so that the result can be compared:
function fastCalcS(a) {
let r0, r1, r2;
r1 = r2 = 0;
for (let i = 0; i < a.length; i++) {
r0 = r1;
r1 = r2;
r2 = 2*(r1 - r0 + 1)*a[i] + r1;
}
return r2;
}
// This function does it the slow way, and executes
// the literal definition of S without optimisation:
function slowCalcS(a) {
let coeff = 2;
let s = 0
for (let i = 0; i < a.length; i++) {
let s_i = 0;
for (let j = 0; j < a.length-i; j++) {
let prod = 1;
for (let k = 0; k <= i; k++) {
prod *= a[j+k];
}
s_i += prod;
}
s += coeff * s_i;
coeff *= 2;
}
return s;
}
var a = [2, 5, 3, 2, 1, 8];
console.log('slow way:', slowCalcS(a));
console.log('fast way:', fastCalcS(a));
In languages that provide a reduce array method (as JavaScript does), the function can look like this (ES6 syntax):
function fastCalcS(a) {
return a.reduce( ([r1, r2], v) => [r2, 2*(r2 - r1 + 1)*v + r2], [0, 0] )[1];
}
var a = [2, 5, 3, 2, 1, 8];
console.log(fastCalcS(a));
A very similar approach to trincot, but starting at the other end leads to another linear algorithm.
If we had just the array {A[n-1]} then the sum would be:
T[n-1] = 2*A[n-1]
If we then try { A[n-2], A[n-1]} we get
T[n-2] = 2*A[n-2] + 2*A[n-1] + 4*A[n-2]*A[n-1]
= T[n-1] + 2*A[n-2]*( 1 + 2*A[n-1])
Continuing this way we get the recursions
T[n-k] = T[n-k+1] + 2*A[n-k]* K[n-k+1]
K[n-k] = 1 + 2*A[n-k]*K[n-k+1]
In C
int64_t sum( int64_t n, const int64_t* A)
{
int64_t K = 1;
int64_t T = 0;
int64_t i = n;
while( --i >= 0)
{ T += 2*K*A[i];
K = 1 + 2*A[i]*K;
}
return T;
}
Question is such that given a set of numbers we have to write a recursive program which prints all possible combination after pairing consecutive numbers or leaving them single.
<div>
Ex set 1,2,3,4,5,6
Output
<ul>
<li>1,2,3,4,5,6</li>
<li>12,3,4,5,6</li>
<li>1,23,4,5,6</li>
<li>1,2,34,5,6</li>
<li>1,2,3,45,6</li>
<li>1,2,3,4,56</li>
<li>12,34,5,6</li>
<li>12,3,45,6</li>
<li>12,3,4,56</li>
<li>1,23,45,6</li>
<li>1,23,4,56</li>
<li>1,2,34,56</li>
<li>12,34,56</li>
</div>
I use c++ to code.
Suppose the given set is a(a[0], a[1], ..., a[n - 1]), and the length of a is n
And the current answer is saved in b
void dfs(int pos, int depth)
{
if(pos >= n)
for(int i = 0; i < depth; ++i)
printf("%d%c", b[i], i == depth - 1 ? '\n' : ',');
else
{
b[depth] = a[pos];
dfs(pos + 1, depth + 1);
if(pos + 1 < n)
{
int c = 1, x = a[pos];
while(x) c *= 10, x /= 10;
b[depth] = a[pos] * c + a[pos + 1];
dfs(pos + 2, depth + 1);
}
}
}
An array contains both positive and negative elements, find the maximum subarray whose sum equals 0.
The link in the current accepted answer requires to sign up for a membership and I do not its content.
This algorithm will find all subarrays with sum 0 and it can be easily modified to find the minimal one or to keep track of the start and end indexes. This algorithm is O(n).
Given an int[] input array, you can create an int[] tmp array where tmp[i] = tmp[i - 1] + input[i]; Each element of tmp will store the sum of the input up to that element(prefix sum of array).
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 sum of the input till j is equal to the sum till k and this means that the sum of the portion of the array between j and k is 0! Specifically the 0 sum subarray 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;
NOTE: An empty array has sum 0 and it's minimal and this special case should be brought up as well in an interview. Then the interviewer will say that doesn't count but that's another problem! ;)
The implementation can be done in different ways including using a HashMap with pairs but be careful with the special case in the NOTE section above.
Example:
int[] input = {4, 6, 3, -9, -5, 1, 3, 0, 2}
int[] tmp = {4, 10, 13, 4, -1, 0, 3, 3, 5}
Value 4 in tmp at index 0 and 3 ==> sum tmp 1 to 3 = 0, length (3 - 1) + 1 = 3
Value 0 in tmp at index 5 ==> sum tmp 0 to 5 = 0, length (5 - 0) + 1 = 6
Value 3 in tmp at index 6 and 7 ==> sum tmp 7 to 7 = 0, length (7 - 7) + 1 = 1
****UPDATE****
Assuming that in our tmp array we end up with multiple element with the same value then you have to consider every identical pair in it! Example (keep in mind the virtual '0' at index '-1'):
int[] array = {0, 1, -1, 0}
int[] tmp = {0, 1, 0, 0}
By applying the same algorithm described above the 0-sum subarrays are delimited by the following indexes (included):
[0] [0-2] [0-3] [1-2] [1-3] [3]
Although the presence of multiple entries with the same value might impact the complexity of the algorithm depending on the implementation, I believe that by using an inverted index on tmp (mapping a value to the indexes where it appears) we can keep the running time at O(n).
This is one the same lines as suggested by Gevorg but I have used a hash map for quick lookup. O(n) complexity used extra space though.
private static void subArraySumsZero()
{
int [] seed = new int[] {1,2,3,4,-9,6,7,-8,1,9};
int currSum = 0;
HashMap<Integer, Integer> sumMap = new HashMap<Integer, Integer>();
for(int i = 0 ; i < seed.length ; i ++)
{
currSum += seed[i];
if(currSum == 0)
{
System.out.println("subset : { 0 - " + i + " }");
}
else if(sumMap.get(currSum) != null)
{
System.out.println("subset : { "
+ (sumMap.get(currSum) + 1)
+ " - " + i + " }");
sumMap.put(currSum, i);
}
else
sumMap.put(currSum, i);
}
System.out.println("HASH MAP HAS: " + sumMap);
}
The output generated has index of elements (zero based):
subset : { 1 - 4 }
subset : { 3 - 7 }
subset : { 6 - 8 }
1. Given A[i]
A[i] | 2 | 1 | -1 | 0 | 2 | -1 | -1
-------+---|----|--------|---|----|---
sum[i] | 2 | 3 | 2 | 2 | 4 | 3 | 2
2. sum[i] = A[0] + A[1] + ...+ A[i]
3. build a map<Integer, Set>
4. loop through array sum, and lookup map to get the set and generate set, and push <sum[i], i> into map.
Complexity O(n)
Here's my implementation, it's the obvious approach so it's probably sub-optimized, but at least its clear. Please correct me if i'm wrong.
Starts from each index of the array and calculates and compares the individual sums (tempsum) with the desired sum (in this case, sum = 0). Since the integers are signed, we must calculate every possible combination.
If you don't need the full list of sub-arrays, you can always put conditions in the inner loop to break out of it. (Say you just want to know if such a sub-array exists, just return true when tempsum = sum).
public static string[] SubArraySumList(int[] array, int sum)
{
int tempsum;
List<string> list = new List<string>();
for (int i = 0; i < array.Length; i++)
{
tempsum = 0;
for (int j = i; j < array.Length; j++)
{
tempsum += array[j];
if (tempsum == sum)
{
list.Add(String.Format("[{0}-{1}]", i, j));
}
}
}
return list.ToArray();
}
Calling the function:
int[] array = SubArraySumList(new int { 0, -1, 1, 0 }, 0));
Printing the contents of the output array:
[0-0], [0-2], [0-3], [1-2], [1-3], [3-3]
Following solution finds max length subarray with a given sum k without using dynamic programming, but using simple rescursion. Here i_s is start index and i_e is end index for the current value of sum
##Input the array and sum to be found(0 in your case)
a = map(int,raw_input().split())
k = int(raw_input())
##initialize total sum=0
totalsum=0
##Recursive function to find max len 0
def findMaxLen(sumL,i_s,i_e):
if i_s<len(a)-1 and i_e>0:
if sumL==k:
print i_s, i_e
return (i_s,i_e)
else:
x = findMaxLen(sumL-a[i_s],i_s+1,i_e)
y = findMaxLen(sumL-a[i_e],i_s,i_e-1)
if x[1]-x[0]>y[1]-y[0]:
return x
else:
return y
else:
##Result not there
return (-1,-1)
## find total sum
for i in range(len(a)):
totalsum += a[i]
##if totalsum==0, max array is array itself
if totalsum == k:
print "seq found at",0,len(a)-1
##else use recursion
else:
print findMaxLen(totalsum,0,len(a)-1)
Time complexity is O(n) and space complexity is O(n) due to recursive memory stack
Here's an O(n) implementation in java
The idea is to iterate through the given array and for every element arr[i], calculate sum of elements form 0 to i, store each sum in HashMap.
If an element is 0, it's considerd as a a ZeroSum sub array.
if sum became 0, then there is a ZeroSum sub array, from 0 to i.
If the current sum has been seen before in HashMap, then there is a ZeroSum sub array, from that point to i.
Code:
import java.util.*;
import java.lang.*;
class Rextester
{
private static final int[] EMPTY = {};
// Returns int[] if arr[] has a subarray with sero sum
static int[] findZeroSumSubarray(int arr[])
{
if (arr.length == 0) return EMPTY;
// Creates an empty hashMap hM
HashMap<Integer, Integer> hM = new HashMap<Integer, Integer>();
// Initialize sum of elements
int sum = 0;
for (int i = 0; i < arr.length; i++)
{
sum += arr[i];
if (arr[i] == 0) //Current element is 0
{
return new int[]{0};
}
else if (sum == 0) // sum of elements from 0 to i is 0
{
return Arrays.copyOfRange(arr, 0, i+1);
}
else if (hM.get(sum) != null) // sum is already present in hash map
{
return Arrays.copyOfRange(arr, hM.get(sum)+1, i+1);
}
else
{
// Add sum to hash map
hM.put(sum, i);
}
}
// We reach here only when there is no subarray with 0 sum
return null;
}
public static void main(String arg[])
{
//int arr[] = {};
int arr[] = { 2, -3, 1, 4, 6}; //Case left
//int arr[] = { 0, 2, -3, 1, 4, 6}; //Case 0
//int arr[] = { 4, 2, -3, 1, 4}; // Case middle
int result[] = findZeroSumSubarray(arr);
if (result == EMPTY){
System.out.println("An empty array is ZeroSum, LOL");
}
else if ( result != null){
System.out.println("Found a subarray with 0 sum :" );
for (int i: result) System.out.println(i);
}
else
System.out.println("No Subarray with 0 sum");
}
}
Please see the experiment here: http://rextester.com/PAKT41271
An array contains positive and negative numbers. Find the sub-array that has the maximum sum
public static int findMaxSubArray(int[] array)
{
int max=0,cumulativeSum=0,i=0,start=0,end=0,savepoint=0;
while(i<array.length)
{
if(cumulativeSum+array[i]<0)
{
cumulativeSum=0;
savepoint=start;
start=i+1;
}
else
cumulativeSum=cumulativeSum+array[i];
if(cumulativeSum>max)
{
max=cumulativeSum;
savepoint=start;
end=i;
}
i++;
}
System.out.println("Max : "+max+" Start indices : "+savepoint+" end indices : "+end);
return max;
}
Below codes can find out every possible sub-array that has a sum being a given number, and (of course) it can find out the shortest and longest sub-array of that kind.
public static void findGivenSumSubarray(int arr[], int givenSum) {
int sum = 0;
int sStart = 0, sEnd = Integer.MAX_VALUE - 1; // Start & end position of the shortest sub-array
int lStart = Integer.MAX_VALUE - 1, lEnd = 0; // Start & end position of the longest sub-array
HashMap<Integer, ArrayList<Integer>> sums = new HashMap<>();
ArrayList<Integer> indices = new ArrayList<>();
indices.add(-1);
sums.put(0, indices);
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
indices = sums.get(sum - givenSum);
if(indices != null) {
for(int index : indices) {
System.out.println("From #" + (index + 1) + " to #" + i);
}
if(i - indices.get(indices.size() - 1) < (sEnd - sStart + 1)) {
sStart = indices.get(indices.size() - 1) + 1;
sEnd = i;
}
if(i - indices.get(0) > (lEnd - lStart + 1)) {
lStart = indices.get(0) + 1;
lEnd = i;
}
}
indices = sums.get(sum);
if(indices == null) {
indices = new ArrayList<>();
}
indices.add(i);
sums.put(sum, indices);
}
System.out.println("Shortest sub-arry: Length = " + (sEnd - sStart + 1) + ", [" + sStart + " - " + sEnd + "]");
System.out.println("Longest sub-arry: Length = " + (lEnd - lStart + 1) + ", [" + lStart + " - " + lEnd + "]");
}
Hope this help you.
private static void subArrayZeroSum(int array[] , int findSum){
Map<Integer,HashSet<Integer>> map = new HashMap<Integer,HashSet<Integer>>();
int sum = 0;
for(int index = 0 ; index < array.length ; index ++){
sum +=array[index];
if(array[index] == findSum){
System.out.println(" ["+index+"]");
}
if(sum == findSum && index > 0){
System.out.println(" [ 0 , "+index+" ]");
}
if(map.containsKey(sum)){
HashSet<Integer> set = map.get(sum);
if(set == null)
set = new HashSet<Integer>();
set.add(index);
map.put(sum, set);
for(int val : set){
if(val + 1 != index && (val + 1) < index){
System.out.println("["+(val + 1) +","+index+" ]");
}
}
}else{
HashSet<Integer> set = map.get(sum);
if(set == null)
set = new HashSet<Integer>();
set.add(index);
map.put(sum, set);
}
}
}
One of the solution:
Let's say we have an array of integer,
int[] arr = {2,1,-1,-2};
We will traverse using the for loop until we find the number < 0 OR <= 0
i = 2;
With the inner loop, we will traverse assign the value to j = i-1
So, We can able to find the positive value.
for(int i = 0; i<arr.length; i++){
int j = 0;
int sum = arr[i];
if(arr[i] < 0){
j = i - 1;
}
We will have one sum variable, which maintaining the sum of arr[i] and arr[j] and updating the result.
If the sum is < 0 then, we have to move left side of the array and so, we will decrement the j by one, j--
for(j = i-1; j>=0; j--) {
sum = sum + arr[j];
if(sum == 0){
System.out.println("Index from j=" + j+ " to i=" + i);
return true;
}
}
If the sum is > 0 then, we have to move right side of the array and so, we will increment the i
When we find the sum == 0 then we can print the j and i index and return or break the loop.
And so, It's complete in a linear time. As well we don't need to use any other data structure as well.
Another solution to this problem could be:
1. Calculate sum for entire array
2. Now follow following formula to get the largest subarray with sum zero:
Math.max(find(a,l+1,r,sum-a[l]), find(a,l,r-1,sum-a[r]));
where l=left index, r= right index, initially their value=0 and a.length-1
Idea is simple, max size we can get with sum=0, is the size of array then we start skipping elements from left and right recursively, the moment we get sum=0 we stop. Below is the code for same:
static int find(int a[]) {
int sum =0;
for (int i = 0; i < a.length; i++) {
sum = sum+a[i];
}
return find(a, 0, a.length-1, sum);
}
static int find(int a[], int l, int r, int sum) {
if(l==r && sum>0) {
return 0;
}
if(sum==0) {
return r-l+1;
}
return Math.max(find(a,l+1,r,sum-a[l]), find(a,l,r-1,sum-a[r]));
}
Hope this will help.
int v[DIM] = {2, -3, 1, 2, 3, 1, 4, -6, 7, -5, -1};
int i,j,sum=0,counter=0;
for (i=0; i<DIM; i++) {
sum = v[i];
counter=0;
for (j=i+1; j<DIM;j++) {
sum += v[j];
counter++;
if (sum == 0) {
printf("Sub-array starting from index %d, length %d.\n",(j-counter),counter +1);
}
}
}