Skip to content

Commit 1945deb

Browse files
committed
Solution to "Trionic Array II" hard problem
1 parent ed36e58 commit 1945deb

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.github.dkoval.leetcode.challenge;
2+
3+
import java.util.ArrayList;
4+
import java.util.function.BiFunction;
5+
6+
/**
7+
* <a href="https://leetcode.com/problems/trionic-array-ii/">Trionic Array II (Hard)</a>
8+
* <p>
9+
* You are given an integer array nums of length n.
10+
* <p>
11+
* A trionic subarray is a contiguous subarray nums[l...r] (with 0 <= l < r < n) for which there exist indices l < p < q < r such that:
12+
* <ul>
13+
* <li>nums[l...p] is strictly increasing,</li>
14+
* <li>nums[p...q] is strictly decreasing,</li>
15+
* <li>nums[q...r] is strictly increasing.</li>
16+
* </ul>
17+
* Return the maximum sum of any trionic subarray in nums.
18+
* <p>
19+
* Constraints:
20+
* <ul>
21+
* <li>4 <= n = nums.length <= 10^5</li>
22+
* <li>-10^9 <= nums[i] <= 10^9</li>
23+
* <li>It is guaranteed that at least one trionic subarray exists.</li>
24+
* </ul>
25+
*/
26+
public interface TrionicArray2 {
27+
28+
long maxSumTrionic(int[] nums);
29+
30+
class TrionicArray2Rev1 implements TrionicArray2 {
31+
32+
@Override
33+
public long maxSumTrionic(int[] nums) {
34+
final var n = nums.length;
35+
36+
// step 1: find decreasing chunks
37+
final var decreasing = new ArrayList<Interval>();
38+
var start = -1;
39+
var sum = 0L;
40+
for (var i = 0; i < n - 1; i++) {
41+
if (nums[i] > nums[i + 1]) {
42+
if (start < 0) {
43+
start = i;
44+
}
45+
sum += nums[i];
46+
} else {
47+
if (start >= 0) {
48+
sum += nums[i];
49+
decreasing.add(new Interval(start, i, sum));
50+
start = -1;
51+
sum = 0;
52+
}
53+
}
54+
}
55+
56+
// step 2: find increasing chunks to the left and to the right of a decreasing one
57+
var best = Long.MIN_VALUE;
58+
for (var interval : decreasing) {
59+
if (interval.start == 0 || interval.end == n - 1) {
60+
continue;
61+
}
62+
63+
var leftSum = maxSumOfIncreasing(nums, interval.start, -1, (a, b) -> a > b);
64+
var rightSum = maxSumOfIncreasing(nums, interval.end, 1, (a, b) -> a < b);
65+
best = Math.max(best, interval.sum + leftSum + rightSum);
66+
}
67+
return best;
68+
}
69+
70+
private long maxSumOfIncreasing(int[] nums, int start, int step, BiFunction<Integer, Integer, Boolean> comparator) {
71+
var i = start;
72+
var total = 0L;
73+
var best = Long.MIN_VALUE;
74+
while (i > 0 && i < nums.length - 1 && comparator.apply(nums[i], nums[i + step])) {
75+
i += step;
76+
total += nums[i];
77+
best = Math.max(best, total);
78+
}
79+
return best;
80+
}
81+
82+
record Interval(int start, int end, long sum) {
83+
}
84+
}
85+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.github.dkoval.leetcode.challenge
2+
3+
import com.github.dkoval.leetcode.challenge.TrionicArray2.TrionicArray2Rev1
4+
import org.junit.jupiter.api.Assertions.assertEquals
5+
import org.junit.jupiter.api.Nested
6+
import org.junit.jupiter.api.extension.ExtensionContext
7+
import org.junit.jupiter.params.ParameterizedTest
8+
import org.junit.jupiter.params.provider.Arguments
9+
import org.junit.jupiter.params.provider.Arguments.arguments
10+
import org.junit.jupiter.params.provider.ArgumentsProvider
11+
import org.junit.jupiter.params.provider.ArgumentsSource
12+
import org.junit.jupiter.params.support.ParameterDeclarations
13+
import java.util.stream.Stream
14+
15+
internal class TrionicArray2Test {
16+
17+
class InputArgumentsProvider : ArgumentsProvider {
18+
19+
override fun provideArguments(
20+
parameters: ParameterDeclarations,
21+
context: ExtensionContext
22+
): Stream<out Arguments> = Stream.of(
23+
arguments(
24+
intArrayOf(0, -2, -1, -3, 0, 2, -1),
25+
-4L
26+
),
27+
arguments(
28+
intArrayOf(1, 4, 2, 7),
29+
14L
30+
)
31+
)
32+
}
33+
34+
@Nested
35+
inner class TrionicArray2Rev1Test {
36+
37+
@ParameterizedTest
38+
@ArgumentsSource(InputArgumentsProvider::class)
39+
fun `should return the maximum sum of any trionic subarray in nums`(nums: IntArray, expected: Long) {
40+
TrionicArray2Rev1().test(nums, expected)
41+
}
42+
}
43+
}
44+
45+
private fun TrionicArray2.test(nums: IntArray, expected: Long) {
46+
val actual = maxSumTrionic(nums)
47+
assertEquals(expected, actual)
48+
}

0 commit comments

Comments
 (0)