package me.ramswaroop.arrays; import me.ramswaroop.common.MaxHeap; import java.util.ArrayDeque; import java.util.Arrays; /** * Created by IntelliJ IDEA. * * @author: ramswaroop * @date: 9/3/15 * @time: 9:21 PM */ public class MaxInAllSubArrays { /** * Naive approach. * <p/> * Finds the maximum element in each and every sub-array * in {@param a} of size {@param k}. * <p/> * Time complexity: O(n*k), or more precisely O((n-k) * k) * * @param a * @param k */ public static int[] maxInAllSubArraysOfSizeKNaive(int[] a, int k) { int[] maxElements = new int[a.length - k + 1]; int[] kElements; for (int i = 0; i <= a.length - k; i++) { kElements = Arrays.copyOfRange(a, i, i + k); /** * maxHeapify() can't be used because to call maxHeapify() on i because left(i) and right (i) should * already satisfy the max heap property which isn't true in this case. */ MaxHeap maxHeap = new MaxHeap(kElements); maxHeap.buildMaxHeap(); maxElements[i] = maxHeap.findMax(); } return maxElements; } /** * Finds the maximum element in each and every sub-array * in {@param a} of size {@param k}. * * Time complexity: O(n) * Auxiliary Space: O(k) * * @param a * @param k * @return */ public static int[] maxInAllSubArraysOfSizeK(int[] a, int k) { int i, j = 0; int[] result = new int[a.length - k + 1]; /** * Create a Double Ended Queue, Qi that will store indexes of array elements * The queue will store indexes of useful elements in every window and it will * maintain decreasing order of values from front to rear in Qi, i.e, * arr[Qi.front[]] to arr[Qi.rear()] are sorted in decreasing order. */ ArrayDeque<Integer> deque = new ArrayDeque<>(); for (i = 0; i < k; i++) { // remove smaller elements on left side of current element while (!deque.isEmpty() && a[i] > a[deque.peekLast()]) { deque.removeLast(); } deque.addLast(i); } for (; i < a.length; i++) { result[j++] = a[deque.peekFirst()]; // remove elements that are outside window k while (!deque.isEmpty() && deque.peekFirst() <= i - k) { deque.removeFirst(); } // remove smaller elements on left side of current element while (!deque.isEmpty() && a[i] > a[deque.peekLast()]) { deque.removeLast(); } deque.addLast(i); } // for max in last k elements result[j] = a[deque.peekFirst()]; return result; } public static void main(String a[]) { System.out.println(Arrays.toString(maxInAllSubArraysOfSizeKNaive(new int[]{1, 2, 3, 1, 4, 5, 2, 3, 6}, 3))); System.out.println(Arrays.toString(maxInAllSubArraysOfSizeKNaive(new int[]{8, 5, 10, 7, 9, 4, 15, 12, 90, 13}, 4))); System.out.println(Arrays.toString(maxInAllSubArraysOfSizeK(new int[]{1, 2, 3, 1, 4, 5, 2, 3, 6}, 3))); System.out.println(Arrays.toString(maxInAllSubArraysOfSizeK(new int[]{8, 5, 10, 7, 9, 4, 15, 12, 90, 13}, 4))); } }