Create an array of smaller and greater , similar to what was done for a subsequence of size 3. In addition to this, it also has an betweenSmallerAndCurrent array that stores the index of the value that is between the smallest and the current element - both by value and by index. More specific:
betweenSmallerAndCurrent[i] = -1 or input[smaller[i]] < input[betweenSmallerAndCurrent[i]] < input[value[i]] and smaller[i] < betweenSmallerAndCurrent[i] < value[i]
Building this should be fairly simple.
You simply return the index i , where everything betweenSmallerAndCurrent[i] , smaller[betweenSmallerAndCurrent[i]] and greater[i] all initialized. Note that we cannot just check smaller[i] , because we may have something like [2,3,1,4,5] , and in this case, when we go to 4 , the second smallest value is 3 is up to the current smallest value of 1 .
Example:
Indices: 0 1 2 3 4 5 6 7 Input: 12 11 10 5 6 2 9 30 smaller: -1 -1 -1 -1 3 -1 5 5 betweenSmallerAndCurrent: -1 -1 -1 -1 -1 -1 4 4 greater: 7 7 7 7 7 7 7 -1
The only index with all initialized values โโis 6 (input value 9).
Java code: (not tested)
void find4Numbers(int arr[], int n) { int max = n-1; //Index of maximum element from right side int min = 0, second = -1; //Index of minimum element from left side int i; // Create an array that will store index of a smaller // element on left side. If there is no smaller element // on left side, then smaller[i] will be -1. int[] smaller = new int[n]; int[] betweenSmallerAndCurrent = new int[n]; smaller[0] = -1; // first entry will always be -1 betweenSmallerAndCurrent[0] = -1; for (i = 1; i < n; i++) { if (arr[i] <= arr[min]) { min = i; smaller[i] = -1; betweenSmallerAndCurrent[i] = -1; } else { smaller[i] = min; if (second != -1 && arr[second] < arr[i]) betweenSmallerAndCurrent[i] = second; else betweenSmallerAndCurrent[i] = -1; if (second == -1 || arr[i] < arr[second]) second = i; } } // Create another array that will store index of a // greater element on right side. If there is no greater // element on right side, then greater[i] will be -1. int[] greater = new int[n]; greater[n-1] = -1; // last entry will always be -1 for (i = n-2; i >= 0; i--) { if (arr[i] >= arr[max]) { max = i; greater[i] = -1; } else greater[i] = max; } // Make sure they're right System.out.println(Arrays.toString(smaller)); System.out.println(Arrays.toString(betweenSmallerAndCurrent)); System.out.println(Arrays.toString(greater)); // Now find a number which has both a greater number on // right side and smaller number on left side for (i = 0; i < n; i++) { if (betweenSmallerAndCurrent[i] != -1 && smaller[betweenSmallerAndCurrent[i]] != -1 && greater[i] != -1) { System.out.printf("%d %d %d %d\n", arr[smaller[betweenSmallerAndCurrent[i]]], arr[betweenSmallerAndCurrent[i]], arr[i], arr[greater[i]]); return; } } // If we reach number, then there are no such 3 numbers System.out.println("No such triplet found"); }
You may notice that the main code changes from this , besides C and Java conversion and added initializations, it is in a loop that sets up smaller . The code should be pretty straightforward - try translating it into words if you have any problems.
Test .