I have a program that is supposed to decrypt a number to its primes. The primes also have an order: for instance, 2 is the 1st prime number, 3 is the second 5 is the third and so on. The indexes are 1 is for a, two is for b, three is for c and so on. I don't know how to compare the two array lists in order to assign an index to each prime so I can decode a word which is encrypted in the number 72216017. The number 72216017 has the primes 17,19,47,67,71. If 2,3,5,7,11... are a,b,c,d,e... these five prime numbers make up the word ghost, I just don't know how to assign and sort these numbers by their index.
package name;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PrimeFactorsEffective {
private static int z;
private int w = z;
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<Integer>();
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
if (n > 1) {
factors.add(n);
System.out.println(factors);
z = Collections.max(factors);
}
}
return factors;
}
public static void main(String[] args) {
System.out.println("Primefactors of 72216017");
for (Integer integer : primeFactors(72216017)) {
System.out.println(integer);
}
List<Integer> factors1 = new ArrayList<Integer>();
List<String> index1 = new ArrayList<String>();
int i;
int element = 0;
int num = 0;
int maxCheck = z; // maxCheck limit till which you want to find prime numbers
boolean isPrime = true;
String primeNumbersFound = "";
//Start loop 1 to maxCheck
for (i = 1; i <= maxCheck; i++) {
isPrime = CheckPrime(i);
if (isPrime) {
primeNumbersFound = primeNumbersFound + i + " ";
factors1.add(i);
factors1.get(num);
}
}
System.out.println("Prime numbers from 1 to " + maxCheck + " are:");
System.out.println(factors1);
}
public static boolean CheckPrime(int numberToCheck) {
int remainder;
for (int i = 2; i <= numberToCheck / 2; i++) {
remainder = numberToCheck % i;
if (remainder == 0) {
return false;
}
}
return true;
}
}
You can store the primes in a List (primes in this list will be in increasing order). Now you can use Collections.BinarySearch to get the index of the prime for which you wan to find the corresponding alphabet. Once you got the index (index here according to you starts from 1, so a's index is 1, b's index is 2, c's index is 3 and so on) you can do simply something like char currentCharacter = (char) ('a' + primeIndex - 1) and the variable currentCharacter will store the alphabet corresponding to primeIndex.
Some other minor things that I'd like to suggest:
Which checking whether a number is prime or not, you can simply check upto square-root of numberToCheck. So you can replace your loop for (int i = 2; i <= numberToCheck / 2; i++) to for (int i = 2; i*i <= numberToCheck; i++). Note that It is not a good idea to calculate square-root using Math.sqrt, instead you can have a condition like i*i <= numberToCheck.
Please refrain from naming your packages that seem to be random.
As of Java SE 7 explicit type-arguments while initializing the list are not required. You can replace List<Integer> factors1 = new ArrayList<Integer>() with List<Integer> factors1 = new ArrayList<>(). Please read this for more information.
Your factor method don't really look good to me, it don't give correct results. Please see the following method that gives correct result:
{{
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<>();
for (int i = 2; n>1; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
z = Collections.max(factors);
return factors;
}
Given two non-negative numbers num1 and num2 represented as strings, return the sum of num1 and num2.
The length of both num1 and num2 is less than 5100.
Both num1 and num2 contain only digits 0-9.
Both num1 and num2 do not contain any leading zeros.
You must not use any built-in BigInteger library or convert the inputs to integer directly.
I tried my solution but it doesn't work. Suggestions?
public class Solution {
public String addStrings(String num1, String num2) {
double multiplier = Math.pow(10, num1.length() - 1);
int sum = 0;
for (int i = 0; i < num1.length(); i++){
sum += ((((int) num1.charAt(i)) - 48) * multiplier);
multiplier /= 10;
}
multiplier = Math.pow(10, num2.length() - 1);
for (int i = 0; i < num2.length(); i++){
sum += ((((int) num2.charAt(i)) - 48) * multiplier);
multiplier /= 10;
}
return "" + sum;
}
}
You must not use any built-in BigInteger library or convert the inputs to integer directly.
Note that you are adding two integers of up to 5100 digits each. That is not that max value, but the max number of digits.
An int (your sum variable) cannot hold values like that. BigInteger can, but you're not allowed to use it.
So, add the numbers like you would on paper: Add last digits, write lower digit of the sum as last digit of result, and carry-over a one if needed. Repeat for second-last digit, third-last digit, etc. until done.
Since the sum will be at least the number of digits of the longest input value, and may be one longer, you should allocate a char[] of length of longest input plus one. When done, construct final string using String(char[] value, int offset, int count), with an offset of 0 or 1 as needed.
The purpose of this question is to add the numbers in the string form. You should not try to convert the strings to integers. The description says the length of the numbers could be up to 5100 digits. So the numbers are simply too big to be stored in integers and doubles. For instance In the following line:
double multiplier = Math.pow(10, num1.length() - 1);
You are trying to store 10^5100 in a double. In IEEE 754 binary floating point standard a double can a store number from ±4.94065645841246544e-324 to ±1.79769313486231570e+308. So your number won't fit. It will instead turn into Infinity. Even if it fits in double it won't be exact and you will encounter some errors in your follow up calculations.
Because the question specifies not to use BigInteger or similar libraries you should try and implement string addition yourself.
This is pretty straightforward just implement the exact algorithm you follow when you add two numbers on paper.
Here is working example of adding two strings without using BigInteger using char array as intermediate container. The point why double can't be used has been explained on #Tempux answer. Here the logic is similar to how adding two numbers on paper works.
public String addStrings(String num1, String num2) {
int carry = 0;
int m = num1.length(), n = num2.length();
int len = m < n ? n : m;
char[] res = new char[len + 1]; // length is maxLen + 1 incase of carry in adding most significant digits
for(int i = 0; i <= len ; i++) {
int a = i < m ? (num1.charAt(m - i - 1) - '0') : 0;
int b = i < n ? (num2.charAt(n - i - 1) - '0') : 0;
res[len - i] = (char)((a + b + carry) % 10 + '0');
carry = (a + b + carry) / 10;
}
return res[0] == '0' ? new String(res, 1, len) : new String(res, 0, len + 1);
}
This snippet is relatively small and precise because here I didn't play with immutable String which is complicated/messy and yield larger code. Also one intuition is - there is no way of getting larger output than max(num1_length, num2_length) + 1 which makes the implementation simple.
You have to addition as you do on paper
you can't use BigInteger and the String Length is 5100, so you can not use int or long for addition.
You have to use simple addition as we do on paper.
class AddString
{
public static void main (String[] args) throws java.lang.Exception
{
String s1 = "98799932345";
String s2 = "99998783456";
//long n1 = Long.parseLong(s1);
//long n2 = Long.parseLong(s2);
System.out.println(addStrings(s1,s2));
//System.out.println(n1+n2);
}
public static String addStrings(String num1, String num2) {
StringBuilder ans = new StringBuilder("");
int n = num1.length();
int m = num2.length();
int carry = 0,sum;
int i, j;
for(i = n-1,j=m-1; i>=0&&j>=0;i--,j--){
int a = Integer.parseInt(""+num1.charAt(i));
int b = Integer.parseInt(""+num2.charAt(j));
//System.out.println(a+" "+b);
sum = carry + a + b;
ans.append(""+(sum%10));
carry = sum/10;
}
if(i>=0){
for(;i>=0;i--){
int a = Integer.parseInt(""+num1.charAt(i));
sum = carry + a;
ans.append(""+(sum%10));
carry = sum/10;
}
}
if(j>=0){
for(;j>=0;j--){
int a = Integer.parseInt(""+num2.charAt(j));
sum = carry + a;
ans.append(""+(sum%10));
carry = sum/10;
}
}
if(carry!=0)ans.append(""+carry);
return ans.reverse().toString();
}
}
You can run the above code and see it works in all cases, this could be written in more compact way, but that would have been difficult to understand for you.
Hope it helps!
you can use this one that is independent of Integer or BigInteger methods
public String addStrings(String num1, String num2) {
int l1 = num1.length();
int l2 = num2.length();
if(l1==0){
return num2;
}
if(l2==0){
return num1;
}
StringBuffer sb = new StringBuffer();
int minLen = Math.min(l1, l2);
int carry = 0;
for(int i=0;i<minLen;i++){
int ind = l1-i-1;
int c1 = num1.charAt(ind)-48;
ind = l2-i-1;
int c2 = num2.charAt(ind)-48;
int add = c1+c2+carry;
carry = add/10;
add = add%10;
sb.append(add);
}
String longer = null;
if(l1<l2){
longer = num2;
}
else if(l1>l2){
longer = num1;
}
if(longer!=null){
int l = longer.length();
for(int i=minLen;i<l;i++){
int c1 = longer.charAt(l-i-1)-48;
int add = c1+carry;
carry = add/10;
add = add%10;
sb.append(add);
}
}
return sb.reverse().toString();
}
The method takes two string inputs representing non-negative integers and returns the sum of the integers as a string. The algorithm works by iterating through the digits of the input strings from right to left, adding each digit and any carryover from the previous addition, and appending the resulting sum to a StringBuilder. Once both input strings have been fully processed, any remaining carryover is appended to the output string. Finally, the string is reversed to produce the correct output order.
Hope this will solve the issue.!
public string AddStrings(string num1, string num2)
{
int i = num1.Length - 1, j = num2.Length - 1, carry = 0;
StringBuilder sb = new StringBuilder();
while (i >= 0 || j >= 0 || carry != 0) {
int x = i >= 0 ? num1[i--] - '0' : 0;
int y = j >= 0 ? num2[j--] - '0' : 0;
int sum = x + y + carry;
sb.Append(sum % 10);
carry = sum / 10;
}
char[] chars = sb.ToString().ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
Previous solutions have excess code. This is all you need.
class ShortStringSolution {
static String add(String num1Str, String num2Str) {
return Long.toString(convert(num1Str) + convert(num2Str));
}
static long convert(String numStr) {
long num = 0;
for(int i = 0; i < numStr.length(); i++) {
num = num * 10 + (numStr.charAt(i) - '0');
}
return num;
}
}
class LongStringSolution {
static String add(String numStr1, String numStr2) {
StringBuilder result = new StringBuilder();
int i = numStr1.length() - 1, j = numStr2.length() - 1, carry = 0;
while(i >= 0 || j >= 0) {
if(i >= 0) {
carry += numStr1.charAt(i--) - '0';
}
if(j >= 0) {
carry += numStr2.charAt(j--) - '0';
}
if(carry > 9) {
result.append(carry - 10);
carry = 1;
} else {
result.append(carry);
carry = 0;
}
}
if(carry > 0) {
result.append(carry);
}
return result.reverse().toString();
}
}
public class Solution {
static String add(String numStr1, String numStr2) {
if(numStr1.length() < 19 && numStr2.length() < 19) {
return ShortStringSolution.add(numStr1, numStr2);
}
return LongStringSolution.add(numStr1, numStr2);
}
}
For the sake of comprehension of the question
your method's name is addition
you are trying to do a power operation but the result is stored in a variable named multiplication...
there is more than one reason why that code doesnt work...
You need to do something like
Integer.parseInt(string)
in order to parse strings to integers
here the oficial doc
I am trying to write a DP solution for the problem: count total number of sub-sequences possible of an array whose elements' sum is divisible by k.
I have written the following solution. But it is not giving the correct result. Like in the following code snippet, the array is {1, 2, 1} and k = 3. So expected total number of sub sequences divisible by 3 is 2, but the actual result is 3 which is clearly incorrect.
Please point out my mistake.
private int countDP(int[] a, int k)
{
int L = a.length;
int[][] DP = new int[L][k];
for(int i = 0; i < DP.length; i++)
{
for(int j = 0; j < DP[0].length; j++)
DP[i][j] = -1;
}
int res = _countDP(a, k, DP, 0, 0);
return res;
}
private int _countDP(int[] a, int k, int[][] DP, int idx, int m) //Not giving the correct result.
{
if(idx == a.length)
return m == 0 ? 1 : 0;
if(DP[idx][m] != -1)
return DP[idx][m];
int ans = 0;
ans = _countDP(a, k, DP, idx + 1, m);
ans += _countDP(a, k, DP, idx + 1, (m + a[idx]) % k);
return DP[idx][m] = ans;
}
public static void main(String[] args)
{
CountSubnsequences cs = new CountSubnsequences();
int[] a = {1, 2, 1};
int k = 3;
int total1 = cs.countDP(a, k);
System.out.println("Total numeber of sub sequences: " + total1);
}
Let s denote a sequence of length N, and K be a given divisor.
dp[i][j] = the number of subsequences of s[0..i] with remainder equal to j. We will compute dp for all 0 <= i < N and 0 <= j < K.
dp[i][j] = 0 for all (i, j)
dp[0][0] += 1
dp[0][s[0] mod K] += 1
for i = 1 .. N - 1
for j = 0 .. K - 1
dp[i][j] = dp[i - 1][j]
for j = 0 .. K - 1
dp[i][(j + s[i]) mod K] += dp[i - 1][j]
The result is dp[N - 1][0]
Python code of #piotrekg2 solution.
Looks good!
from typing import List
# dp[i][j] = the number of subsequences of length i with remainder equal to j.
def count_subseq(s: List[int],k):
n = len(s)
dp = [0]*k
dp[0] = 1 # i=0, remainder=0, only 1 subseq
for i in range(1,n+1):
dp2 = dp.copy() # copy previous i-length results: results without s[i] in subseq
for j in range(k):
dp2[(j+s[i-1])%k] += dp[j]
dp = dp2
return dp[0]
if __name__ == '__main__':
print(count_subseq([2,3,5,8],5))
print(count_subseq([5,5,5],5))
Faced the same issue. But ended up getting an answer.
The answer returning will be always 1 more than the total possible subsequences. This is because we know that 0 is always being a valid answer. So, if let's say you do not pick any single element from the array, then also the sum=0. So, it considers it as a valid answer and increments our answer by 1. So, to get the actual answer Just decrement the returned value by 1.
int fun(int i,int s)
{
if(i==1){
if(s-a[i]!=0 && (s-a[i])%k==0)
return 1;
else
return 0;}
else{
if((s-a[i])%k==0){
return 1+fun(i-1,s-a[i])+fun(i-1,s);
}
else{
return fun(i-1,s-a[i])+fun(i-1,s);
}
}
}
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;
}
}