package org.bench4q.agent.test;

import org.junit.Test;

public class Solution {
	public double findMedianSortedArrays(int A[], int B[]) {
		if (A == null && B == null) {
			throw new IllegalArgumentException();
		}
		if (A == null || A.length == 0) {
			return average(B[B.length / 2], B[(B.length - 1) / 2]);
		} else if (B == null || B.length == 0) {
			return average(A[A.length / 2], A[(A.length - 1) / 2]);
		}
		int firstMedian = (A.length + B.length) / 2 + 1, secondMedian = (A.length
				+ B.length - 1) / 2 + 1;
		if (firstMedian == secondMedian) {
			return find(A, 0, A.length - 1, B, 0, B.length - 1, firstMedian);
		} else {
			return average(
					find(A, 0, A.length - 1, B, 0, B.length - 1, firstMedian),
					find(A, 0, A.length - 1, B, 0, B.length - 1, secondMedian));
		}
	}

	private int find(int[] A, int beginA, int endA, int[] B, int beginB,
			int endB, int k) {
		if (beginA > endA) {
			return B[beginB + k - 1];
		} else if (beginB > endB) {
			return A[beginA + k - 1];
		}
		int pivotIndex = (beginA + endA) / 2, pivotValue = A[pivotIndex], leftLengthA = pivotIndex
				- beginA;
		int leftLengthB = getLeftLength(B, beginB, endB, pivotValue);
		if (k <= leftLengthA + leftLengthB) {
			return find(A, beginA, pivotIndex - 1, B, beginB, beginB
					+ leftLengthB - 1, k);
		} else if (k == leftLengthA + leftLengthB + 1) {
			return pivotValue;
		} else {
			return find(A, pivotIndex + 1, endA, B, beginB + leftLengthB, endB,
					k - leftLengthA - leftLengthB - 1);
		}
	}

	private int getLeftLength(int[] A, int begin, int end, int pivotValue) {
		int mid = (begin + end) / 2;
		int beginIn = begin, endIn = end;
		while (beginIn < endIn) {
			if (A[mid] > pivotValue) {
				endIn = mid - 1;
			} else if (A[mid] == pivotValue) {
				break;
			} else {
				beginIn = mid + 1;
			}
			mid = (beginIn + endIn) / 2;
		}
		return A[mid] < pivotValue ? mid - begin + 1 : mid - begin;
	}

	private double average(int partner1, int partner2) {
		return ((double) partner1 + (double) partner2) / 2;
	}

	@Test
	public void test3() {
		System.out.println(this.findMedianSortedArrays(new int[] { 1, 2, 3 },
				new int[] { 1, 2, 2 }));
	}

	public void test1() {
	}
}