You are given an array arr of N integers. For each index i, you are required to determine the number of contiguous subarrays that fulfill the following conditions:
- The value at index i must be the maximum element in the contiguous subarrays, and
- These contiguous subarrays must either start from or end on index i.
Signature int[] countSubarrays(int[] arr) Input
- Array arr is a non-empty list of unique integers that range between 1 to 1,000,000,000
- Size N is between 1 and 1,000,000
Output An array where each index i contains an integer denoting the maximum number of contiguous subarrays of arr[i]
Example:
arr = [3, 4, 1, 6, 2]
output = [1, 3, 1, 5, 1]
Explanation:
For index 0 - [3] is the only contiguous subarray that starts (or ends) with 3, and the maximum value in this subarray is 3.
For index 1 - [4], [3, 4], [4, 1]
For index 2 - [1]
For index 3 - [6], [6, 2], [1, 6], [4, 1, 6], [3, 4, 1, 6]
For index 4 - [2]
So, the answer for the above input is [1, 3, 1, 5, 1]
Solution
import java.io.*;
import java.util.*;
// Add any extra import statements you may need here
class Main {
// Add any helper functions you may need here
int[] countSubarrays(int[] arr) {
int n = arr.length;
Stack<Integer> stack = new Stack<>();
int[] left = new int[n];
for (int i = 0; i < n; i++) {
while (stack.size() > 0 && arr[stack.peek()] < arr[i]) {
left[i] += left[stack.pop()];
}
left[i]++;
stack.push(i);
}
stack.clear();
int[] right = new int[n];
// [3, 4, 1, 6, 2]
for (int i = n - 1; i >= 0; i--) {
while (stack.size() > 0 && arr[stack.peek()] < arr[i]) {
right[i] += right[stack.pop()];
}
right[i]++;
stack.push(i);
}
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = left[i] + right[i] - 1;
}
return res;
}
int[] countSubarrays2(int[] arr) {
// Write your code here
int n = arr.length;
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = 1;
res[i] += countSubarraysLeft(i, arr);
res[i] += countSubarraysRight(i, arr);
}
return res;
}
int countSubarraysLeft(int i, int[] arr) {
int count = 0;
int j = i - 1;
while (j >= 0 && arr[j] < arr[i]) {
j--;
count++;
}
return count;
}
int countSubarraysRight(int i, int[] arr) {
int count = 0;
int j = i + 1;
while (j < arr.length && arr[j] < arr[i]) {
j++;
count++;
}
return count;
}
// These are the tests we use to determine if the solution is correct.
// You can add your own at the bottom.
int test_case_number = 1;
void check(int[] expected, int[] output) {
int expected_size = expected.length;
int output_size = output.length;
boolean result = true;
if (expected_size != output_size) {
result = false;
}
for (int i = 0; i < Math.min(expected_size, output_size); i++) {
result &= (output[i] == expected[i]);
}
char rightTick = '\u2713';
char wrongTick = '\u2717';
if (result) {
System.out.println(rightTick + " Test #" + test_case_number);
}
else {
System.out.print(wrongTick + " Test #" + test_case_number + ": Expected ");
printIntegerArray(expected);
System.out.print(" Your output: ");
printIntegerArray(output);
System.out.println();
}
test_case_number++;
}
void printIntegerArray(int[] arr) {
int len = arr.length;
System.out.print("[");
for(int i = 0; i < len; i++) {
if (i != 0) {
System.out.print(", ");
}
System.out.print(arr[i]);
}
System.out.print("]");
}
public void run() {
int[] test_1 = {3, 4, 1, 6, 2};
int[] expected_1 = {1, 3, 1, 5, 1};
int[] output_1 = countSubarrays(test_1);
check(expected_1, output_1);
int[] test_2 = {2, 4, 7, 1, 5, 3};
int[] expected_2 = {1, 2, 6, 1, 3, 1};
int[] output_2 = countSubarrays(test_2);
check(expected_2, output_2);
// Add your own test cases here
}
public static void main(String[] args) {
new Main().run();
}
}