Bash Max Double Slice Sum
max_double_slice_sum() {
local -n _arr="$1"
local _size=${#_arr[@]}
if (( _size < 3 )); then
echo 0
return
fi
local -a _p1 _p2
_p1[1]=0
_p2[_size-2]=0
local _i
for ((_i = 2; _i < _size - 1; _i++)); do
local _left=$(( _p1[_i-1] + _arr[_i-1] ))
(( _left < 0 )) && _left=0
_p1[_i]=$_left
local _right=$(( _p2[_size-_i] + _arr[_size-_i] ))
(( _right < 0 )) && _right=0
_p2[_size-_i-1]=$_right
done
local _sum=$(( _p1[1] + _p2[1] ))
for ((_i = 1; _i < _size - 1; _i++)); do
local _cand=$(( _p1[_i] + _p2[_i] ))
if (( _cand > _sum )); then _sum=$_cand; fi
done
echo "$_sum"
}
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
C++ Max Double Slice Sum
#include <algorithm>
#include <vector>
long long maxDoubleSliceSum(const std::vector<int>& a)
{
int size = static_cast<int>(a.size());
if (size < 3) {
return 0;
}
std::vector<long long> p1(size, 0);
std::vector<long long> p2(size, 0);
for (int i = 2; i < size - 1; ++i) {
p1[i] = std::max<long long>(0, p1[i - 1] + a[i - 1]);
p2[size - i - 1] = std::max<long long>(0, p2[size - i] + a[size - i]);
}
long long sum = p1[1] + p2[1];
for (int i = 1; i < size - 1; ++i) {
sum = std::max(sum, p1[i] + p2[i]);
}
return sum;
}
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
C# Max Double Slice Sum
static long MaxDoubleSliceSum(int[] a)
{
var size = a.Length;
if (size < 3)
{
return 0;
}
var p1 = new long[size];
var p2 = new long[size];
p1[1] = 0;
p2[size - 2] = 0;
for (int i = 2; i < size - 1; i++)
{
p1[i] = Math.Max(0, p1[i - 1] + a[i - 1]);
p2[size - i - 1] = Math.Max(0, p2[size - i] + a[size - i]);
}
var sum = p1[1] + p2[1];
for (int i = 1; i < size - 1; i++)
{
sum = Math.Max(sum, p1[i] + p2[i]);
}
return sum;
}
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
Elixir Max Double Slice Sum
defmodule MaxDoubleSliceSum do
def max_double_slice_sum(a) when length(a) < 3, do: 0
def max_double_slice_sum(a) do
size = length(a)
a_map = a |> Enum.with_index() |> Map.new(fn {v, i} -> {i, v} end)
p1 = build_p1(size, a_map)
p2 = build_p2(size, a_map)
1..(size - 2)
|> Enum.map(fn i -> Map.get(p1, i) + Map.get(p2, i) end)
|> Enum.max()
end
defp build_p1(size, a_map) do
Enum.reduce(2..(size - 2)//1, %{1 => 0}, fn i, p1 ->
value = max(0, Map.get(p1, i - 1) + Map.get(a_map, i - 1))
Map.put(p1, i, value)
end)
end
defp build_p2(size, a_map) do
Enum.reduce(2..(size - 2)//1, %{size - 2 => 0}, fn i, p2 ->
key = size - i - 1
value = max(0, Map.get(p2, size - i) + Map.get(a_map, size - i))
Map.put(p2, key, value)
end)
end
end
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
Erlang Max Double Slice Sum
-module(max_double_slice_sum).
-export([max_double_slice_sum/1]).
max_double_slice_sum(A) ->
Size = length(A),
case Size < 3 of
true -> 0;
false ->
Arr = array:from_list(A),
P1 = build_p1(Arr, Size),
P2 = build_p2(Arr, Size),
lists:max([array:get(I, P1) + array:get(I, P2) || I <- lists:seq(1, Size - 2)])
end.
build_p1(Arr, Size) ->
P0 = array:set(1, 0, array:new(Size)),
lists:foldl(fun(I, Acc) ->
V = max(0, array:get(I - 1, Acc) + array:get(I - 1, Arr)),
array:set(I, V, Acc)
end, P0, lists:seq(2, Size - 2)).
build_p2(Arr, Size) ->
P0 = array:set(Size - 2, 0, array:new(Size)),
lists:foldl(fun(J, Acc) ->
V = max(0, array:get(J + 1, Acc) + array:get(J + 1, Arr)),
array:set(J, V, Acc)
end, P0, lists:seq(Size - 3, 1, -1)).
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
Go Max Double Slice Sum
func maxDoubleSliceSum(a []int) int {
size := len(a)
if size < 3 {
return 0
}
p1 := make([]int, size)
p2 := make([]int, size)
p1[1] = 0
p2[size-2] = 0
for i := 2; i < size-1; i++ {
if v := p1[i-1] + a[i-1]; v > 0 {
p1[i] = v
}
if v := p2[size-i] + a[size-i]; v > 0 {
p2[size-i-1] = v
}
}
sum := p1[1] + p2[1]
for i := 1; i < size-1; i++ {
if s := p1[i] + p2[i]; s > sum {
sum = s
}
}
return sum
}
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
Haskell Max Double Slice Sum
import Data.Array (Array, array, listArray, (!))
maxDoubleSliceSum :: [Int] -> Int
maxDoubleSliceSum a
| n < 3 = 0
| otherwise = maximum [p1 ! i + p2 ! i | i <- [1 .. n - 2]]
where
n = length a
arr = listArray (0, n - 1) a :: Array Int Int
-- p1 ! i = best sum of a slice ending just before index i, growing left to right
p1list = scanl (\acc i -> max 0 (acc + arr ! (i - 1))) 0 [2 .. n - 2]
p1 = listArray (1, n - 2) p1list :: Array Int Int
-- p2 ! i = best sum of a slice starting just after index i, growing right to left
p2list = scanl (\acc k -> max 0 (acc + arr ! (k + 1))) 0 [n - 3, n - 4 .. 1]
p2 = array (1, n - 2) (zip [n - 2, n - 3 .. 1] p2list) :: Array Int Int
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
Java Max Double Slice Sum
public class Solution {
public static int maxDoubleSliceSum(int[] a) {
int size = a.length;
if (size < 3) {
return 0;
}
int[] p1 = new int[size];
int[] p2 = new int[size];
p1[1] = 0;
p2[size - 2] = 0;
for (int i = 2; i < size - 1; i++) {
p1[i] = Math.max(0, p1[i - 1] + a[i - 1]);
p2[size - i - 1] = Math.max(0, p2[size - i] + a[size - i]);
}
int sum = p1[1] + p2[1];
for (int i = 1; i < size - 1; i++) {
sum = Math.max(sum, p1[i] + p2[i]);
}
return sum;
}
}
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
Lisp Max Double Slice Sum
(defun max-double-slice-sum (a)
(let* ((vec (coerce a 'vector))
(size (length vec)))
(if (< size 3)
0
(let ((p1 (make-array size :initial-element 0))
(p2 (make-array size :initial-element 0)))
(setf (aref p1 1) 0)
(setf (aref p2 (- size 2)) 0)
(loop for i from 2 below (1- size)
do (progn
(setf (aref p1 i) (max 0 (+ (aref p1 (1- i)) (aref vec (1- i)))))
(setf (aref p2 (- size i 1)) (max 0 (+ (aref p2 (- size i)) (aref vec (- size i)))))))
(let ((sum (+ (aref p1 1) (aref p2 1))))
(loop for i from 1 below (1- size)
do (setf sum (max sum (+ (aref p1 i) (aref p2 i)))))
sum)))))
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
PHP Max Double Slice Sum
function maxDoubleSliceSum(array $a): int
{
$size = count($a);
if ($size < 3) {
return 0;
}
$p1[1] = 0;
$p2[$size - 2] = 0;
for ($i = 2; $i < ($size - 1); $i++) {
$p1[$i] = max(0, $p1[$i - 1] + $a[$i - 1]);
$p2[$size - $i - 1] = max(0, $p2[$size - $i] + $a[$size - $i]);
}
$sum = $p1[1] + $p2[1];
for ($i = 1; $i < ($size - 1); $i++) {
$sum = max($sum, $p1[$i] + $p2[$i]);
}
return $sum;
}
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.