I have this question I am trying to solve. I have tried coding for the past 4 hours.
An integer is defined to be a Smart number if it is an element in the infinite sequence
1, 2, 4, 7, 11, 16 …
Note that 2-1=1, 4-2=2, 7-4=3, 11-7=4, 16-11=5 so for k>1, the kth element of the sequence is equal to the k-1th element + k-1. For example, for k=6, 16 is the kth element and is equal to 11 (the k-1th element) + 5 ( k-1).
Write function named isSmart that returns 1 if its argument is a Smart number, otherwise it returns 0. So isSmart(11) returns 1, isSmart(22) returns 1 and isSmart(8) returns 0
I have tried the following code to
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = isSmart(11);
System.out.println(x);
}
public static int isSmart(int n) {
int[] y = new int[n];
int j = 0;
for (int i = 1; i <= n; i++) {
y[j] = i;
j++;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i <= y.length; i++) {
int diff = 0;
y[j] = y[i+1] - y[i] ;
y[i] = diff;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
When I test it with 11 it is giving me 0 but it shouldn't. Any idea how to correct my mistakes?
It can be done in a simpler way as follows
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
int x = isSmart(11);
System.out.println("Ans: "+x);
}
public static int isSmart(int n) {
//------------ CHECK THIS LOGIC ------------//
int[] y = new int[n];
int diff = 1;
for (int i = 1; i < n; i++) {
y[0] =1;
y[i] = diff + y[i-1];
diff++;
}
//------------ CHECK THIS LOGIC ------------//
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
One of the problems is the way that your populating your array.
The array can be populated as such
for(int i = 0; i < n; i++) {
y[i] = (i == 0) ? 1 : y[i - 1] + i;
}
The overall application of the function isSmart can be simplified to:
public static int isSmart(int n) {
int[] array = new int[n];
for(int i = 0; i < n; i++) {
array[i] = (i == 0) ? 1 : array[i - 1] + i;
}
for (int i = 0; i < array.length; i++) {
if (array[i] == n) return 1;
}
return 0;
}
Note that you don't need to build an array:
public static int isSmart(int n) {
int smart = 1;
for (int i = 1; smart < n; i++) {
smart = smart + i;
}
return smart == n ? 1 : 0;
}
Here is a naive way to think of it to get you started - you need to fill out the while() loop. The important thing to notice is that:
The next value of the sequence will be the number of items in the sequence + the last item in the sequence.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
System.out.println(isSmart(11));
}
public static int isSmart(int n) {
ArrayList<Integer> sequence = new ArrayList<Integer>();
// Start with 1 in the ArrayList
sequence.add(1);
// You need to keep track of the index, as well as
// the next value you're going to add to your list
int index = 1; // or number of elements in the sequence
int nextVal = 1;
while (nextVal < n) {
// Three things need to happen in here:
// 1) set nextVal equal to the sum of the current index + the value at the *previous* index
// 2) add nextVal to the ArrayList
// 3) incriment index by 1
}
// Now you can check to see if your ArrayList contains n (is Smart)
if (sequence.contains(n)) { return 1; }
return 0;
}
}
First think of a mathematical solution.
Smart numbers form a sequence:
a0 = 1
an+1 = n + an
This gives a function for smart numbers:
f(x) = ax² + bx + c
f(x + 1) = f(x) + x = ...
So the problem is to find for a given y a matching x.
You can do this by a binary search.
int isSmart(int n) {
int xlow = 1;
int xhigh = n; // Exclusive. For n == 0 return 1.
while (xlow < xhigh) {
int x = (xlow + xhigh)/2;
int y = f(x);
if (y == n) {
return 1;
}
if (y < n) {
xlow = x + 1;
} else {
xhigh = x;
}
}
return 0;
}
Yet smarter would be to use the solution for x and look whether it is an integer:
ax² + bx + c' = 0 where c' = c - n
x = ...
I was playing around with this and I noticed something. The smart numbers are
1 2 4 7 11 16 22 29 ...
If you subtract one you get
0 1 3 6 10 15 21 28 ...
0 1 2 3 4 5 6 7 ...
The above sequence happens to be the sum of the first n numbers starting with 0 which is n*(n+1)/2. So add 1 to that and you get a smart number.
Since n and n+1 are next door to each other you can derive them by reversing the process.
Take 29, subtract 1 = 28, * 2 = 56. The sqrt(56) rounded up is 8. So the 8th smart number (counting from 0) is 29.
Using that information you can detect a smart number without a loop by simply reversing the process.
public static int isSmart(int v) {
int vv = (v-1)*2;
int sq = (int)Math.sqrt(vv);
int chk = (sq*(sq+1))/2 + 1;
return (chk == v) ? 1 : 0;
}
Using a version which supports longs have verified this against the iterative process from 1 to 10,000,000,000.
I am doing this Array Manipulation problem from hackerrank and it tells me compile error is Terminated due to timeout.
For small arrays my method work perfectly. This error only happens for bigger array values.
Here is the question link. Question Here
Starting with a 1-indexed array of zeros and a list of operations, for each operation add a value to each of the array element between two given indices, inclusive. Once all operations have been performed, return the maximum value in your array.
For example, the length of your array of zeros . Your list of queries is as follows:
a b k
1 5 3
4 8 7
6 9 1
Add the values of between the indices and inclusive:
index -> 1 2 3 4 5 6 7 8 9 10
[0,0,0, 0, 0,0,0,0,0, 0]
[3,3,3, 3, 3,0,0,0,0, 0]
[3,3,3,10,10,7,7,7,0, 0]
[3,3,3,10,10,8,8,8,1, 0]
The largest value is after all operations are performed.
Given below is my method.
static long arrayManipulation(int n, int[][] queries) {
long max = 0L;
long[] arr = new long[n];
for (int i = 0; i < n; i++) {
arr[i] = 0L;
}
for (int i = 0; i < queries.length; i++) {
int[] q = queries[i];
int start = q[0] - 1;
int end = q[1] - 1;
int val = q[2];
long tempMax = updateVal(start, end, val, arr);
if (tempMax > max) {
max = tempMax;
}
}
return max;
}
static long updateVal(int start, int end, int val, long[] arr) {
long max = 0L;
for (int i = start; i <= end; i++) {
arr[i] = arr[i] + val;
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
Given below are few test classes that doesn't work with my code.
Test1 Test2 Test3
Please help me to figure this out. I searched for lots of answers based on java.
But I couldn't understand them.
This is my last resort. Please help.
Updated after Kanahaiya's answer
static long arrayManipulation(int n, int[][] queries) {
long max = 0L;
int a, b, k;
int[] arr = new int[n + 2];
for (int i = 0; i < queries.length; i++) {
a = queries[i][0];
b = queries[i][1];
k = queries[i][2];
for (int j = 0; j < arr.length; j++) {
if (j >= a) {
arr[j] = arr[j] + k;
}
if (j > b) {
arr[j] = arr[j] - k;
}
}
}
Arrays.sort(arr);
max = arr[arr.length - 1];
return max;
}
Brute-force solution is not going to work here due to the given time constraint.
That is the reason you will get the time out error.
So you need to optimize your code which can be done with the help of prefix sum array.
instead of adding k to all the elements within a range from a to b in an array, accumulate the difference array
Whenever we add anything at any index into an array and apply prefix sum algorithm the same element will be added to every element till the end of the array.
ex- n=5, m=1, a=2 b=5 k=5
i 0.....1.....2.....3.....4.....5.....6 //take array of size N+2 to avoid index out of bound
A[i] 0 0 0 0 0 0 0
Add k=5 to at a=2
A[a]=A[a]+k // start index from where k element should be added
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 0 0 0 0
now apply prefix sum algorithm
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 5 5 5 5
so you can see K=5 add to all the element till the end after applying prefix sum but we don't have to add k till the end. so to negate this effect we have to add -K also after b+1 index so that only from [a,b] range only will have K element addition effect.
A[b+1]=A[b]-k // to remove the effect of previously added k element after bth index.
that's why adding -k in the initial array along with +k.
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 0 0 0 -5
Now apply prefix sum Array
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 0 5 5 5 5 0
You can see now K=5 got added from a=2 to b=5 which was expected.
Here we are only updating two indices for every query so complexity will be O(1).
Now apply the same algorithm in the input
# 0.....1.....2.....3.....4.....5.....6 //taken array of size N+2 to avoid index out of bound
5 3 # 0 0 0 0 0 0 0
1 2 100 # 0 100 0 -100 0 0 0
2 5 100 # 0 100 100 -100 0 0 -100
3 4 100 # 0 100 100 0 0 -100 -100
To calculate the max prefix sum, accumulate the difference array to 𝑁 while taking the maximum accumulated prefix.
After performing all the operation now apply prefix sum Array
i 0.....1.....2.....3.....4.....5.....6
A[i] 0 100 200 200 200 100 0
Now you can traverse this array to find max which is 200.
traversing the array will take O(N) time and updating the two indices for each query will take O(1)* number of queries(m)
overall complexity=O(N)+O(M)
= O(N+M)
it means = (10^7+10^5) which is less than 10^8 (per second)
Note: If searching for video tutorial , you must check it out here for detailed explanation.
First of all, in case you don't realize it, Terminated due to timeout is not a compilation error, it means that your implementation is too slow. The challenge is not to implement any correct solution to the problem. The solution must also be efficient. Since your solution is inefficient, it fails for large inputs due to being too slow.
Since the number of queries seems to be 2 orders of magnitude smaller than the length of the array (100K vs. 10M in the 3 test cases you posted), it would be more efficient to work just with the queries instead of actually updating the array.
I'm not going to give you an implementation, but I'll suggest an algorithm that should be more efficient than your current implementation.
I suggest you process the queries as follows:
Add the first query to a list of processed queries, which will contain queries with disjoint sub-array ranges. This list will be sorted by the first array index (you will keep it sorted by adding new elements in the proper position).
For each query not processed yet, find all the processed queries that overlap it (you can do it using binary search to improve performence).
Split the current query in a way that the resulting queries will each be either fully contained in an existing processed query or not contained in each existing processed query.
For each of the queries created in the split:
if their range is equal to the range of an existing processed query, add the value of the query to the processed query.
If their range is not contained in any existing processed query, add that query as a new processed query.
If their range is partially contained in an existing processed query, split the processed query.
I'm not sure if my explanation is clear enough. I'll show an example with the
1 5 3
4 8 7
6 9 1
input:
Add 1 5 3 to the list of processed queries.
Process 4 8 7: There is one processed query the overlaps it - 1 5 3.
Split 4 8 7 into two sub-queries : 4 5 7 and 6 8 7.
4 5 7 is contained in 1 5 3, so split 1 5 3 into 1 3 3 and 4 5 3+7
6 8 7 is not contained in any processed queries, so add it as is.
Now the processed queries are:
1 3 3
4 5 10
6 8 7
Process 6 9 1: There is one processed query that overlaps it: 6 8 7.
Split 6 9 1 into two sub queries : 6 8 1 and 9 9 1.
6 8 1 has the same range a 6 8 7, which will become 6 8 7+1
9 9 1 is not contained in any processed queries, so add it as is.
Now the processed queries are:
1 3 3
4 5 10
6 8 8
9 9 1
As you process the queries you keep track of the max processed query value, so after you process all the queries you know that the max value is 10.
static long arrayManipulation(int n, int[][] queries)
{
// To Avoid "Index was outside the bounds of the array." exception
long[] numbers = new long[n + 1];
for(int i = 0; i < queries.length; i++)
{
int a = queries[i][0] - 1;
int b = queries[i][1];
int k = queries[i][2];
numbers[a] += k;
numbers[b] -= k;
}
// Calculate sum(s)
int max=0;
for(int i = 1; i < numbers.length; i++)
{
numbers[i] += numbers[i - 1];
if(numbers[i]>max)
{
max=numbers[i];
}
}
return max;
}
import java.io.*;
import java.util.InputMismatchException;
import java.util.Random;
public class Solution {
public static void main(String[] args) {
InputStream inputStream = System.in;
InputReader in = new InputReader(inputStream);
int n = in.readInt();
int m = in.readInt();
long[] list = new long[n+3];
while(m-- > 0) {
int a = in.readInt();
int b = in.readInt();
long k = in.readLong();
list[a] += k;
list[b+1] -= k;
}
long max = 0;
long c = 0;
for (int i = 1; i <= n; i++) {
c += list[i];
max = Math.max(max, c);
}
System.out.println(max);
}
}
class InputReader {
private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar;
private int numChars;
private SpaceCharFilter filter;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
public int peek() {
if (numChars == -1)
return -1;
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
return -1;
}
if (numChars <= 0)
return -1;
}
return buf[curChar];
}
public int readInt() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public long readLong() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
long res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public boolean isSpaceChar(int c) {
if (filter != null)
return filter.isSpaceChar(c);
return isWhitespace(c);
}
public static boolean isWhitespace(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
public boolean isExhausted() {
int value;
while (isSpaceChar(value = peek()) && value != -1)
read();
return value == -1;
}
public interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
Implemented the solution in Java for this problem and its working efficiently. Please try if you needed.
public long arrayManipulation(int n, int[][] queries)
{
if(n==0 || queries==null || queries.length==0){
return -1;
}
long[] computation = new long[n];
for (int i = 0; i < queries.length; i++) {
int a = queries[i][0] - 1;
int b = queries[i][1] - 1;
int k = queries[i][2];
computation[a] += k;
if (b + 1 < n ) {
computation[b + 1] -= k;
}
}
long max = 0; long sum = 0;
for (int i = 0; i < n; i++) {
sum += computation[i];
max = Math.max(max, sum);
}
return max;
}
package arrayProblems;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.*;
public class ArrayManipuations {
public static void main(String[] args) {
int n=10;
int[] arr = new int[n];
List<List<Integer>> nl = new ArrayList<List<Integer>>();
nl=asList(asList(1,5,3),asList(4,8,7),asList(6,9,1));
for(int i=0;i<nl.size();i++) {
for(int j=nl.get(i).get(0);j<=nl.get(i).get(1);j++) {
arr[j-1]=arr[j-1]+nl.get(i).get(2);
}
}
int max = Integer.MIN_VALUE;
for(int k=0;k<n;k++) {
if(max<arr[k]) {
max = arr[k];
arr[k]=max;
}
}
System.out.print(max);
}
}
solution in java for Array Manipulation hackerank ...
code does not pass all the cases because of timeout need suggestions to improve
static long arrayManipulation(int n, int[][] queries) {
ArrayList<Long> list = new ArrayList<Long>(n);
for(int i=0; i<n; i++){
list.add(i,0l);
}
for(int i=0; i<queries.length; i++){
int s = queries[i][0];
int e = queries[i][1];
long k = queries[i][2];
int size = 0;
for(int j = s - 1; j<e; j++){
list.set(j, list.get(j) + k);
}
}
long max =Collections.max(list);
return max;
}
Recently, I tried to solve the Max Double Slice Sum problem in codility which is a variant of max slice problem. My Solution was to look for a slice that has maximum value when its minimum value is taken out. So I implemented max slice, but on the current slice took out the minimum number.
My score was 61 of 100 as it failed during some of the tests, mainly the tests on array including both negative and position numbers.
Could you help me to figure out why the code failed or if there is a better solution for the problem?
The problem is as follows:
A non-empty zero-indexed array A consisting of N integers is given.
A triplet (X, Y, Z), such that 0 ≤ X < Y < Z < N, is called a double slice.
The sum of double slice (X, Y, Z) is the total of A[X + 1] + A[X + 2] + ... + A[Y − 1]+ A[Y + 1] + A[Y + 2] + ... + A[Z − 1].
For example, array A such that:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
contains the following example double slices:
double slice (0, 3, 6), sum is 2 + 6 + 4 + 5 = 17,
double slice (0, 3, 7), sum is 2 + 6 + 4 + 5 − 1 = 16,
double slice (3, 4, 5), sum is 0.
The goal is to find the maximal sum of any double slice.
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty zero-indexed array A consisting of N integers, returns the maximal sum of any double slice.
For example, given:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
the function should return 17, because no double slice of array A has a sum of greater than 17.
Assume that:
N is an integer within the range [3..100,000];
each element of array A is an integer within the range [−10,000..10,000].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
Copyright 2009–2013 by Codility Limited. All Rights Reserved. Unauthorized copying, publication or disclosure prohibited.
And my code is as follows:
public class Solution {
public int solution(int[] A) {
int currentSliceTotal=0;
Integer currentMin=null, SliceTotalBeforeMin =0;
int maxSliceTotal= Integer.MIN_VALUE;
for(int i= 1; i<A.length-1; i++){
if( currentMin==null || A[i] < currentMin ){
if(currentMin!=null ){
if(SliceTotalBeforeMin+currentMin <0){
currentSliceTotal-=SliceTotalBeforeMin;
} else {
currentSliceTotal += currentMin;
}
}
currentMin = A[i];
SliceTotalBeforeMin =currentSliceTotal;
if( SliceTotalBeforeMin<0){
SliceTotalBeforeMin = 0;
currentMin = null;
currentSliceTotal = 0;
}
} else {
currentSliceTotal+= A[i];
}
maxSliceTotal = Math.max(maxSliceTotal, currentSliceTotal);
}
return maxSliceTotal;
}
}
If I have understood the problem correctly, you want to calculate the maximum sum subarray with one element missing.
Your algorithm shall not work for the following case:
1 1 0 10 -100 10 0
In the above case, your algorithm shall identify 1, 1, 0, 10 as the maximum sum sub array and leave out 0 to give 12 as the output. However, you can have 1, 1, 0, 10, -100, 10 as the answer after leaving out -100.
You can use a modified form of Kadane's algorithm that calculates the MAX Sum subarray ending at each index.
For each index, calculate the max_sum_ending_at[i] value by using Kadane's algorithm in forward direction.
For each index, calculate the max_sum_starting_from[i] value by using Kadane's algorithm in reverse direction.
Iterate these arrays simultaneously and choose the 'Y' that has the maximum value of
max_sum_ending_at[Y-1] + max_sum_starting_from[Y+1]
Hello this implementacion has 100 score
int i,n ;
n = A.size();
if (3==n) return 0;
vector<int> max_sum_end(n,0);
vector<int> max_sum_start(n,0);
for (i=1; i< (n-1); i++) // i=0 and i=n-1 are not used because x=0,z=n-1
{
max_sum_end[i] = max ( 0 , max_sum_end[i-1] + A[i] );
}
for (i=n-2; i > 0; i--) // i=0 and i=n-1 are not used because x=0,z=n-1
{
max_sum_start[i] = max ( 0 , max_sum_start[i+1] + A[i] );
}
int maxvalue,temp;
maxvalue = 0;
for (i=1; i< (n-1); i++)
{
temp = max_sum_end[i-1] + max_sum_start[i+1];
if ( temp > maxvalue) maxvalue=temp;
}
return maxvalue ;
This is a Java 100/100 Solution:
https://codility.com/demo/results/demoVUMMR9-JH3/
class Solution {
public int solution(int[] A) {
int[] maxStartingHere = new int[A.length];
int[] maxEndingHere = new int[A.length];
int maxSum = 0, len = A.length;
for(int i = len - 2; i > 0; --i ) {
maxSum = Math.max(0, A[i] + maxSum);
maxStartingHere[i] = maxSum;
}
maxSum = 0;
for(int i = 1; i < len - 1; ++i ) {
maxSum = Math.max(0, A[i] + maxSum);
maxEndingHere[i] = maxSum;
}
int maxDoubleSlice = 0;
for(int i = 0; i < len - 2; ++i) {
maxDoubleSlice = Math.max(maxDoubleSlice, maxEndingHere[i] + maxStartingHere[i+2]);
}
return maxDoubleSlice;
}
}
You can find more information going to this Wikipedia link and in the Programming Pearls book.
Here is my solution
https://github.com/dinkar1708/coding_interview/blob/master/codility/max_slice_problem_max_double_slice_sum.py
Codility 100% in Python
def solution(A):
"""
Idea is use two temporary array and store sum using Kadane’s algorithm
ending_here_sum[i] - the maximum sum contiguous sub sequence ending at index i
starting_here_sum[i] - the maximum sum contiguous sub sequence starting with index i
Double slice sum should be the maximum sum of ending_here_sum[i-1]+starting_here_sum[i+1]
Reference -
https://rafal.io/posts/codility-max-double-slice-sum.html
The sum of double slice (X, Y, Z) is the total of A[X + 1] + A[X + 2] + ... + A[Y - 1] + A[Y + 1] + A[Y + 2] + ... + A[Z - 1].
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
contains the following example double slices:
double slice (0, 3, 6), sum is 2 + 6 + 4 + 5 = 17,
double slice (0, 3, 7), sum is 2 + 6 + 4 + 5 - 1 = 16,
double slice (3, 4, 5), sum is 0.
"""
ar_len = len(A)
ending_here_sum = [0] * ar_len
starting_here_sum = [0] * ar_len
# the maximum sum contiguous sub sequence ending at index i
for index in range(1, ar_len - 2): # A[X + 1] + A[X + 2] + ... + A[Y - 1]
ending_here_sum[index] = max(ending_here_sum[index - 1] + A[index], 0)
# the maximum sum contiguous sub sequence starting with index i
for index in range(ar_len - 2, 1, -1): # A[Y + 1] + A[Y + 2] + ... + A[Z - 1]
starting_here_sum[index] = max(starting_here_sum[index + 1] + A[index], 0)
# Double slice sum should be the maximum sum of ending_here_sum[i-1]+starting_here_sum[i+1]
max_slice_sum = ending_here_sum[0] + starting_here_sum[2]
for index in range(1, ar_len - 1):
max_slice_sum = max(max_slice_sum, ending_here_sum[index - 1] + starting_here_sum[index + 1])
return max_slice_sum
C# solution 100/100
public int solution(int[] A) {
int[] forw = new int[A.Length];
int[] rewi = new int[A.Length];
bool isAllNeg = true;
for (int i = 1; i < A.Length; i++)
{
forw[i] = Math.Max(0, forw[i - 1] + A[i]);
if (A[i] > 0 && isAllNeg) isAllNeg = false;
}
if (isAllNeg)
return 0;
for (int i = A.Length - 2; i >= 0; i--)
{
rewi[i] = Math.Max(0, rewi[i + 1] + A[i]);
}
int maxsum = 0;
for (int i = 1; i < A.Length - 1; i++)
{
maxsum = Math.Max(maxsum, forw[i - 1] + rewi[i + 1]);
}
return maxsum;
}
Without using extra memory, 100/100 C++:
#include <algorithm>
int solution(vector<int> &A) {
int max_slice = 0;
int max_slice_i = 0;
int min_val = 0;
int mss = 0;
int mse = 0;
int s = 1;
int msmv = 0;
int max_slice_i_orig = 0;
int os = 1;
for(size_t i = 1;i < A.size() - 1;i++)
{
int v = max_slice_i;
if(max_slice_i > 0 && A[i] < 0)
{
if(A[i] < min_val)
{
v = max_slice_i_orig;
s = os;
min_val = std::max(A[i], -max_slice_i_orig);
} else
{
v = max_slice_i + A[i];
}
} else
{
v = max_slice_i + A[i];
}
int new_orig_v = max_slice_i_orig + A[i];
if(new_orig_v < 0)
{
max_slice_i_orig = 0;
os = i + 1;
} else
{
max_slice_i_orig = new_orig_v;
}
if(v > 0)
{
max_slice_i = v;
} else {
max_slice_i = 0;
min_val = 0;
s = i + 1;
}
if(max_slice_i > max_slice)
{
mss = s;
mse = i;
msmv = min_val;
max_slice = max_slice_i;
}
}
// if all are positive
if(msmv == 0)
{
if(mss == 1 && mse == A.size() - 2)
{
int min = 10001;
for(int j = mss;j <= mse;j++)
{
if(A[j] < min)
min = A[j];
}
max_slice -= min;
}
}
return max_slice;
}
Javascript implementation based on Abhishek Bansal's solution.100/100 on Codility.
function solution(A) {
let maxsum=0;
let max_end_at=Array(A.length);
let max_start_at=Array(A.length);
max_end_at[0]=max_start_at[A.length-1]=max_end_at[A.length-1]=max_start_at[0]=0;
let {max}=Math;
for(let i=1;i<A.length-1;i++){
max_end_at[i]=max(0,max_end_at[i-1]+A[i]);
}
for(let n=A.length-2;n>0;n--){
max_start_at[n]=max(0,max_start_at[n+1]+A[n]);
}
for(let m=1;m<A.length-1;m++){
maxsum=max(maxsum,max_end_at[m-1]+max_start_at[m+1]);
}
return maxsum;
}
The most clear Python solution among others:
def solution(A):
mid = 1
total = 0
max_slice = 0
for idx, end in enumerate(A[2:-1], start=2):
if total < 0:
mid = idx
total = 0
elif total == 0 and A[idx - 1] > A[mid]:
mid = idx - 1
total = end
else:
if A[mid] > end:
total += A[mid]
mid = idx
else:
total += end
max_slice = max(max_slice, total)
return max_slice
Using the idea from http://en.wikipedia.org/wiki/Maximum_subarray_problem
and Abhishek Bansal's answer above. 100% test pass:
public class Solution {
public int solution(int[] A) {
int[] maxEndingHere = maxEndingHere(A);
int[] maxStartingHere = maxStartingHere(A);
int maxSlice = 0;
for (int i = 1; i < A.length-1;i++) {
maxSlice = Math.max(maxSlice, maxEndingHere[i-1]+maxStartingHere[i+1]);
}
return maxSlice;
}
/**
* Precalculate ending subarrays. Take into account that first and last element are always 0
* #param input
* #return
*/
public static int[] maxEndingHere(int[] input) {
int[] result = new int[input.length];
result[0] = result[input.length-1] = 0;
for (int i = 1; i < input.length-1; i++) {
result[i] = Math.max(0, result[i-1] + input[i]);
}
return result;
}
/**
* Precalculate starting subarrays. Take into account that first and last element are always 0
* #param input
* #return
*/
public static int[] maxStartingHere(int[] input) {
int[] result = new int[input.length];
result[0] = result[input.length-1] = 0;
for (int i = input.length-2; i >= 1; i--) {
result[i] = Math.max(0, result[i+1] + input[i]);
}
return result;
}
}
Vb.net version of the above solution is as below:
Private Function solution(A As Integer()) As Integer
' write your code in VB.NET 4.0
Dim Slice1() As Integer = Ending(A)
Dim slice2() As Integer = Starting(A)
Dim maxSUM As Integer = 0
For i As Integer = 1 To A.Length - 2
maxSUM = Math.Max(maxSUM, Slice1(i - 1) + slice2(i + 1))
Next
Return maxSUM
End Function
Public Shared Function Ending(input() As Integer) As Integer()
Dim result As Integer() = New Integer(input.Length - 1) {}
result(0) = InlineAssignHelper(result(input.Length - 1), 0)
For i As Integer = 1 To input.Length - 2
result(i) = Math.Max(0, result(i - 1) + input(i))
Next
Return result
End Function
Public Shared Function Starting(input() As Integer) As Integer()
Dim result As Integer() = New Integer(input.Length - 1) {}
result(0) = InlineAssignHelper(result(input.Length - 1), 0)
For i As Integer = input.Length - 2 To 1 Step -1
result(i) = Math.Max(0, result(i + 1) + input(i))
Next
Return result
End Function
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
View result on codility
Here is an alternative solution to the proposed by me before, more readable and understandable:
int solution(vector<int> & A){
if(A.size() < 4 )
return 0;
int maxSum = 0;
int sumLeft = 0;
unordered_map<int, int> leftSums;
leftSums[0] = 0;
for(int i = 2; i < A.size()-1; i++){
sumLeft += A[i-1];
if(sumLeft < 0)
sumLeft = 0;
leftSums[i-1] = sumLeft;
}
int sumRight = 0;
unordered_map<int, int> rightSums;
rightSums[A.size()-1] = sumRight;
for( int i = A.size() - 3; i >= 1; i--){
sumRight += A[i+1];
if(sumRight < 0)
sumRight = 0;
rightSums[i+1] = sumRight;
}
for(long i = 1; i < A.size() - 1; i++){
if(leftSums[i-1] + rightSums[i+1] > maxSum)
maxSum = leftSums[i-1] + rightSums[i+1];
}
return maxSum;
}
Well, I have my solution, may be not the best one bit 100%/100%, according to codility requierments.
#include<vector>
#include<unordered_map>
#include<algorithm>
using namespace std;
int solution(vector<int> &A) {
unordered_map<size_t, int> maxSliceLeftToRight;
maxSliceLeftToRight[1] = 0;
unordered_map<size_t, int> maxSliceRightToLeft;
maxSliceRightToLeft[A.size() - 2] = 0;
int sum = 0;
for (size_t i = 2; i < A.size() - 1; i++) {
int tmpSum = max(sum + A[i - 1], 0);
sum = max(A[i - 1], tmpSum);
maxSliceLeftToRight[i] = sum;
}
sum = 0;
for (size_t i = A.size() - 3; i > 0; i--) {
int tmpSum = max(sum + A[i + 1], 0);
sum = max(A[i + 1], tmpSum);
maxSliceRightToLeft[i] = sum;
}
int maxDoubleSliceSum = 0;
for (auto & entry : maxSliceLeftToRight) {
int maxRight = maxSliceRightToLeft[entry.first];
if (entry.second + maxRight > maxDoubleSliceSum)
maxDoubleSliceSum = entry.second + maxRight;
}
return maxDoubleSliceSum;
}
Here 100% in python,
might not be as elegant as some other solutions above, but considers all possible cases.
def solution(A):
#Trivial cases
if len(A)<=3:
return 0
idx_min=A.index(min(A[1:len(A)-1]))
minval=A[idx_min]
maxval=max(A[1:len(A)-1])
if maxval<0:
return 0
if minval==maxval:
return minval*(len(A)-3)
#Regular max slice if all numbers > 0
if minval>=0:
max_ending=0
max_slice=0
for r in range(1,len(A)-1):
if (r!=idx_min):
max_ending=max(0,A[r]+max_ending)
max_slice = max(max_slice, max_ending)
return max_slice
#Else gets more complicated
else :
#First remove negative numbers at the beginning and at the end
idx_neg=1
while A[idx_neg] <= 0 and idx_neg<len(A) :
A[idx_neg]=0
idx_neg+=1
idx_neg=len(A)-2
#<0 , 0
while A[idx_neg] <= 0 and idx_neg > 0 :
A[idx_neg]=0
idx_neg-=1
#Compute partial positive sum from left
#and store it in Left array
Left=[0]*len(A)
max_left=0
for r in range(1,len(A)-1):
max_left=max(0,A[r]+max_left)
Left[r]=max_left
#Compute partial positive sum from right
#and store it in Right array
max_right=0
Right=[0]*len(A)
for r in range(len(A)-2,0,-1):
max_right=max(0,A[r]+max_right)
Right[r]=max_right
#Compute max of Left[r]+Right[r+2].
#The hole in the middle corresponding
#to Y index of double slice (X, Y, Z)
max_slice=0
for r in range(1,len(A)-3):
max_slice=max(max_slice,Left[r]+Right[r+2])
return max_slice
pass
Think I got it based on Moxis Solution. Tried to point out the Intension.
class Solution {
public int solution(int[] A) {
int n = A.length - 1;
// Array with cummulated Sums when the first Subarray ends at Index i
int[] endingAt = new int[A.length];
int helperSum = 0;
// Optimal Subtotal before all possible Values of Y
for(int i = 1; i < n; ++i ) {
helperSum = Math.max(0, A[i] + helperSum);
endingAt[i] = helperSum;
}
// Array with cummulated Sums when the second Subarray starts at Index i
int[] startingAt = new int[A.length];
helperSum = 0;
// Optimal Subtotal behind all possible Values of Y
for(int i = (n - 1); i > 0; --i ) {
helperSum = Math.max(0, A[i] + helperSum);
startingAt[i] = helperSum;
}
//Searching optimal Y
int sum = 0;
for(int i = 0; i < (n - 1); ++i) {
sum = Math.max(sum, endingAt[i] + startingAt[i+2]);
}
return sum;
}
}
Here is the Python version of the proposed solution with complexity O(N) and %100 correctness and performance.
#Find the maximal sum of any double slice.
#https://app.codility.com/programmers/lessons/9-
#maximum_slice_problem/max_double_slice_sum/
import sys
def solution(A):
n=len(A)
max_sum_endingat=[0]*n
max_sum_startat=[0]*n
if(n<=3):
return 0
else:
for i in range(1,n-1):
max_sum_endingat[i] =max(0,max_sum_endingat[i-1] + A[i])
for i in range(n-2,0,-1):
max_sum_startat[i] =max(0,max_sum_startat[i+1] + A[i])
max_double=-sys.maxsize
for k in range(1,n-1):
max_double=max(max_double,max_sum_endingat[k-1]+max_sum_startat[k+1])
return max_double
This is my solution. It got 92%. Its a modified version of the original concept except I'm keep track of a minimal value to use as the position Y, and I'm shifting the sum of the entire interval accordingly.
Note: If anyone has any idea why it's only 92% feel free to let me know
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
int max = -10001, sum = 0, min=A[1];
for(int i = 1; i < A.length-1; i++){
sum += A[i];
min = Math.min(A[i], min);
max = Math.max(sum-min, max);
if(sum - min < 0){
sum = 0;
min = A[i+1];
}
}
return max;
}
}
Single-loop, no extra memory dynamic programming solution in Python:
def solution(A):
max_gap_sum = 0
gapless_sum, gap_sum = 0, float("-inf")
for v in A[1:-1]:
gapless_sum, gap_sum = max(gapless_sum + v, 0), max(gap_sum + v, gapless_sum)
max_gap_sum = max(max_gap_sum, gap_sum)
return max_gap_sum
Java solution, 100/100
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
int maxEnd = 0, maxSlice = Integer.MIN_VALUE;
for(int val : A) {
maxEnd = Math.max(val, maxEnd + val);
maxSlice = Math.max(maxSlice, maxEnd);
}
return maxSlice;
}
}
I'm kind of new to algorithms and wanted to implement heap sort algorithm.
The algorithm is given as follows:
Parent(i)
return Math.floor(i/2)
Left(i)
return 2i
Right(i)
return 2i+1
Then there is HEAPIFY method that restores the heep property. Algorithm is as follows:
HEAPIFY(A, i)
l = Left(i)
r = Right(i)
if (l <= heap-size[A] and A[l] > A[i]
then largest = l
else largest = i
if r <= heap-size[A] and A[r] > A[largest]
then largest = r
if largest != i
then exchange A[i] <-> A[largest]
HEAPIFY(A, largest)
My Code that implements this method is:
public static void HEAPIFY(int[] A, int i) {
int l = LEFT(i);
int r = RIGHT(i);
int largest = 0;
if (l < A.length && A[l] > A[i]) {
largest = l;
} else {
largest = i;
}
if (r < A.length && A[r] > A[largest]) {
largest = r;
}
if (largest != i) {
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
HEAPIFY(A, largest);
}
}
Now My question is in the book algorithm is shown by drawing the tree of heap and array
so for example array is: [16,14,10,8,7,9,3,2,4,1] and for the tree and also for array it is indexed starting from 1 to n, so Array[1] = 16 and in coding Array[0] = 16. Now i can not adjust the heapify method to start either from index 1 and go up to 1 or somehow make it start from 0 and let the heap be indexed from 0 to n-1.
Sorry if its kind of confusing i'm still confused but i would really appreciate some help.
Thank you guys
Now HEAPIFY works and the following code is code to build the heap:
public static void BUILD_HEAP(int[] A) {
heapSize = A.length;
for (int i = (int) Math.floor(A.length / 2.0); i >= 0; i--) {
HEAPIFY(A, i);
}
}
build heap also works and the only method that doesnot work is heapsort.
public static void HEAPSORT(int[] A) {
BUILD_HEAP(A);
for (int i = A.length-1; i >= 1; i--) {
int temp = A[0];
A[0] = A[i];
A[i] = temp;
heapSize = heapSize-1;
HEAPIFY(A,0);
}
}
this has to sort but when i try to traverse the array after the call of heapsort it does not give the sorted array.
any ideas how to fix heapsort?
Parent(i) return Math.floor(i/2)
=> Parent(i) return Math.floor((i - 1) / 2)
Left(i) return 2i
=> Left(i) return 2i + 1
Right(i) return 2i+1
=> Right(i) return 2i + 2
You can work this out either by fiddling around (which is what I actually did) or considering j = i - 1.
If i' = 2 i and j = i - 1 so i = j + 1
j' = i' - 1 = (2i) - 1 = (2(j + 1)) - 1 = 2j + 1
if you want to start form index 1,then you can initialize the array like this:
[-x,16,14,10,8,7,9,3,2,4,1] -x is the array[0],in other words,you can ignore the element which is in array[0].
if you want to start form index 0,then you have to modify the function LEFT(i) and RIGHT(i).
LEFT(i) return 2*i+1;
RIGHT(i) return 2*i+2;