This problem is from careercup, link
Problem description:
1. qaz is a value for a number where this number is less than the other next values which have indexes larger than the index of this number.
for example: 33 , 25 , 26 , 58 , 41 , 59 -> qaz of (33) = 3 where 33 less than 3 numbers (58 , 41 , 59), qaz of (25) = 4 and not 5 because the index of 33 is less than the index of 25, qaz of (26) = 3 , qaz of (58) = 1 , qaz of (41) = 1 , qaz of (59) = 0.
the question is to find the max qaz.
A brute force solution is to iterate each element, and find how many elements after and larger than it.
A O(nlogn) solution can be achieved by mergesort:
For each array, it has a maxQaz. Let’s consider to merge {33, 48, 26} and {58, 41, 59}.
Final result of 2 arrays are:
{26(0), 33(1), 48(0)}, leftQaz = 1.
{41(1), 58(1), 59(0)}, rightQaz = 1.
-initial added_qaz = 0,
-traverse both arrays from end to the beginning,
-move the pointer which is pointing to the bigger number,
—when moving the pointer of the right sub array, increase added_qaz
—when moving the pointer of the left sub array, apply added_qaz to qaz of pointed element before moving
Because only left sub array is updated.
Now, left sub array should be {26(3), 33(4), 48(2)}. And we know leftQaz is 4.
Before return, we use merge sort to merge 2 subarrays, and got:
{26(3), 33(4), 41(1), 48(2), 58(1), 59(0)}.
Now, we should return max(leftQaz, rightQaz). The result would be 4.
The code is kinda long. Because we use mergesort, so 2 helper arrays for auxiliary space are used.
- package feb;
- public class QAZ {
- public static void main(String[] args) {
- int[] arr = { 7, 8, 2, 3, 4, 5 };
- int qaz = qaz(arr);
- System.out.println(qaz);
- }
- public static int qaz(int[] arr) {
- int[] eleTimes = new int[arr.length];
- int[] helperQaz = new int[arr.length];
- int[] helperTimes = new int[arr.length];
- return qazUtil(arr, eleTimes, 0, arr.length – 1, helperQaz, helperTimes);
- }
- /*
- * Return qaz of arr[]
- * @param qazArr[], qazArr[i] stores the qaz of element arr[i] from arr[start,…,end].
- * @param start, the start position of arr[]
- * @param end, the end position of arr[]
- * @param helperQaz, this is a helper array for mergesort. It helps for arr[]
- * @param helperTimes, a helper array for merge sort. It is temporary place for eleTimes
- */
- private static int qazUtil(int[] arr, int[] qazArr, int start, int end,
- int[] helperQaz, int[] helperTimes) {
- if (start > end) {
- return 0;
- }
- if (start == end) {
- return 0;
- }
- int mid = start + (end – start) / 2;
- int qazLeft = qazUtil(arr, qazArr, start, mid, helperQaz, helperTimes);
- int qazRight = qazUtil(arr, qazArr, mid + 1, end, helperQaz, helperTimes);
- // 1. Update eleTimes in left part.
- int pointerL = mid, pointerR = end;
- int added = 0;
- while (pointerL >= start) {
- while (arr[pointerL] < arr[pointerR] && pointerR >= mid + 1) {
- pointerR–;
- added++;
- }
- qazArr[pointerL] += added;
- qazLeft = (qazArr[pointerL] > qazLeft) ? qazArr[pointerL]: qazLeft;
- pointerL–;
- }
- // 2. Mergesort left and right part into helperQaz, helperTimes
- pointerL = start;
- pointerR = mid + 1;
- int helpIndex = start;
- while (pointerL <= mid && pointerR <= end) {
- if (arr[pointerL] < arr[pointerR]) {
- helperQaz[helpIndex] = arr[pointerL];
- helperTimes[helpIndex] = qazArr[pointerL];
- pointerL++;
- } else {
- helperQaz[helpIndex] = arr[pointerR];
- helperTimes[helpIndex] = qazArr[pointerR];
- pointerR++;
- }
- helpIndex++;
- }
- while (pointerL <= mid) {
- helperQaz[helpIndex] = arr[pointerL];
- helperTimes[helpIndex] = qazArr[pointerL];
- pointerL++;
- helpIndex++;
- }
- while (pointerR <= end) {
- helperQaz[helpIndex] = arr[pointerR];
- helperTimes[helpIndex] = qazArr[pointerR];
- pointerR++;
- helpIndex++;
- }
- // 2.2 Copy result from helperQaz, helperTimes back to arr, eleTimes
- for (int i = start; i <= end; i++) {
- arr[i] = helperQaz[i];
- qazArr[i] = helperTimes[i];
- }
- return Math.max(qazLeft, qazRight);
- }
- }