Problem Array:= [2, 5, 4, 6, 8], k = 3.
divide the problem array in Windows of lenght k=3 =>
windows
index[0-2] => [2,5,4]
index[3-4] => [6,8] // This is from index 3 to end of the problem list
SubArrays
index[0-2] =>[2,5,4]
index[1-3] =>[5,4,6]
index[2-4] =>[4,6,8]
minimum from left in windows
> for window [2,5,4] ==>[2,2,2]
> for window [6,8] ==> [6,6]
> arr1 = minimum from left for window [2,5,4] + minimum from left for window [6,8]
> arr1 = [2,2,2] + [6,6] = [2,2,2,6,6]
> every element at a particular index will be the smaller from all the elements to the left till the start of window index.
> rightMost element will the smallest element in the window. As the solution bubbled from leftMost element.
> [2,2,2] => 2 is smallest, [6,6] => 6 is smallest.
minimum from right in windows => [2,4,4] [6,8] => Arr2 = [2,4,4,6,8]
> for window [2,5,4] ==>[2,4,4]
> for window [6,8] ==> [6,8]
> arr2 = minimum from right for window [2,5,4] + minimum from right for window [6,8]
> arr1 = [2,4,4,6,8]
=> every element at a particular index will be the smaller from all the elements to the right till the end of index.
=> leftMost element will the smallest element in the window. As the solution bubbled from rightMost element.
=> [2,4,4] => 2 is smallest, [6,8] => 6 is smallest.
consider i = index on list
minimum in the window= min(arr2[i],arr1[i+sizeOfWindow-1])
iterateTill = (size of problemList - sizeOfWindow - 1) = 5-3-1 = 2
Loop form 0 -> (iterateTill)
0 => min(arr2[0],arr1[0+3-1]) => min(arr2[0],arr1[2]) => min(2,2) => 2
1 => min(arr2[1],arr1[1+3-1]) => min(arr2[1],arr1[3]) => min(4,6) => 4
2 => min(arr2[2],arr1[2+3-1]) => min(arr2[2],arr1[4]) => min(4,8) => 4
** How This Works **
There are two conditions here.
1. The subarray is completely in the divided window
> eg subarray[0-2] falls completely in the window[0-2]
> arr1[0-2] -> arr1[2] will be the smallest.
> arr2[0-2] -> arr2[0] will be the smallest.
> minSubArray= min(arr2[0],arr1[2]) = min(2,2) = 2
=> Since the index 0-2 falls in the same window. Therefore rightmost in arr1 == leftMost in arr2.
2. The subarray is spanned in two divided windows.
eg subarray[1-3] and subarray[2-5]
Subarray[1-3]
> min(subarray[1-3]) => min(subarray(1-2),subarray(3,3))
> arr2[1] is smaller than all the elements to the right till the end of window.
> arr2[1] = min[problem[1],problem[2]]
similarly,
> arr1[3] = min[problem[3],problem[3]] // start of the window[3-4]
> min(subarray[1-3]) = min(arr2[1],arr1[3]) = min(4,6) => 4
Similarly for subarray [2-5]
> min(subarray[2-4]) => min(subarray(2,2),subarray(3,4))
> arr2[2] = min[problem[2],problem[2]]
similarly,
> arr1[4] = min[problem[3],problem[4]] // start of the window[3-4]
> min(subarray[2-4]) = min(arr2[2],arr1[4]) = min(4,6) => 4
3. The final collection.max will return the maximum value from the minimal list, considering the minimum of all the subarrays is saved in minimaListlist.
I have tried to refactor code with proper names, Please have a look this might help you understand more. The naming in the code is very poor.
public static int process(int sizeOfSubArray, List<Integer> problemList) {
int sizeOfProblemList = problemList.size();
int[] minimumFromLeftInWindow = new int[sizeOfProblemList];
// LeftMost element index 0, will be the smallest element from the start to the index of leftmost element.
minimumFromLeftInWindow[0] = problemList.get(0);
int[] minimumFromRightInWindow = new int[sizeOfProblemList];
// RightMost element will be smallest element from right to the end of the list.
minimumFromRightInWindow[sizeOfProblemList - 1] = problemList.get(sizeOfProblemList - 1);
for (int i = 1; i < sizeOfProblemList; i++) {
if (i % sizeOfSubArray == 0)
minimumFromLeftInWindow[i] = problemList.get(i);
else
minimumFromLeftInWindow[i] = Math.min(minimumFromLeftInWindow[i - 1], problemList.get(i));
// Moving from end of the list to start. That is from right end to left end.
int j = sizeOfProblemList - i - 1;
if ((j + 1) % sizeOfSubArray == 0)
// if the index is of rightMostElement element in window
minimumFromRightInWindow[j] = problemList.get(j);
else
// take the minimum of element to the right of this index and element at this index
// considering the element to the right have bubbled up the minimum element from right.
minimumFromRightInWindow[j] = Math.min(minimumFromRightInWindow[j + 1], problemList.get(j));
}
List<Integer> minimaList = new ArrayList<>();
for (int i = 0; i < sizeOfProblemList - sizeOfSubArray + 1; i++) {
minimaList.add(Math.min(minimumFromLeftInWindow[i + sizeOfSubArray - 1], minimumFromRightInWindow[i]));
}
return Collections.max(minimaList);
}