Im struggling to get the below problem right for a quite a while sometime.
Given an array of ints, is it possible to choose a group of some of the ints, such that the group sums to the given target, with this additional constraint: if there are numbers in the array that are adjacent and the identical value, they must either all be chosen, or none of them chosen. For example, with the array {1, 2, 2, 2, 5, 2}, either all three 2's in the middle must be chosen or not, all as a group. (one loop can be used to find the extent of the identical values).
groupSumClump(0, {8, 2, 2, 1}, 9) → true
groupSumClump(0, {2, 4, 4, 8}, 14) → false
The code is at http://ideone.com/Udk5q
Failing test case scenarios:
groupSumClump(0, {2, 4, 4, 8}, 14) → false -->NegativeArraySizeException
groupSumClump(0, {8, 2, 2, 1}, 9) → true false --> X
i have really tried my best to make it work but alas its failing always.
Please Need your help SO experts to resolve this problem
I will be highly obliged and thankful to you,if you can spare a few minutes to look into my problem as well and help me in acheieving the desired solution.
Method "summate" logic is realy messed up.
It should look something like function "f" here:
Algorithm to find which numbers from a list of size n sum to another number
Quick and dirty fix for your code:
class Demo {
public static void main(String args[]) {
Demo.groupSumClump(0, new int[] { 2, 4, 4, 8 }, 14);
Demo.groupSumClump(0, new int[] {8, 2, 2, 1}, 9);
}
public static void groupSumClump(int start, int[] nums, int target) {
start = 0;
nums = adjacents(start, nums);
for (int a_number = 0; a_number < nums.length; a_number++) {
System.out.println("Array is " + nums[a_number]);
}
summate(nums, 0, 0, target);
System.out.println(false);
}
public static int[] adjacents(int start, int[] nums) {
int sum = 0;
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i] == nums[i + 1]) {
sum += nums[i] + nums[i + 1];
nums[i] = sum;
nums[i + 1] = 0;
}
}
return nums;
}
static void check(int sum, int target) {
if (sum == target) {
System.out.println(true);
System.exit(0);
}
}
static void summate(int[] numbers, int index, int sum, int target) {
check(sum, target);
if (index == numbers.length) {
return;
}
summate(numbers, index + 1, sum + numbers[index], target);
check(sum, target);
summate(numbers, index + 1, sum, target);
check(sum, target);
}
}
public boolean groupSumClump(int start, int[] nums, int target) {
if(start >= nums.length) return target == 0;
if(start < nums.length-1 && nums[start] == nums[start+1]){
int span = 0;
for(int i = start; i < nums.length && nums[i] == nums[start]; i++){
span++;
} if(groupSumClump(start + span, nums, target)) return true;
return groupSumClump(start + span, nums, target - nums[start] * span);
} if(groupSumClump(start + 1, nums, target-nums[start])) return true;
if(groupSumClump(start +1, nums, target)) return true;
return false;
}
Related
The problem is stated:
If we can assign either a positive or negative sign to each integer in
a set of integers, how many ways can we sum the signed integers to
equal a target value? We must use every integer in the set.
Eg [1, 2, 3, 2], target = 0
Two ways [-1, 2, -3, 2], and [1, -2, 3,
-2]
My solution is as follows (java)
public static void main(String[] args) {
int[] nums = {1, 2, 3, 2};
int x = helper(0, 0, nums, 0);
System.out.println(x);
}
private static int helper(int step, int sumSoFar, int[] nums, int target) {
if (step == nums.length) {
return sumSoFar == target ? 1 : 0;
}
return
helper(step + 1, sumSoFar + nums[step], nums, target)
+
helper(step + 1, sumSoFar - nums[step], nums, target);
}
I understand that there are many possible repeated calculations in a brute force solution, but I can't understand if passing in the sumSoFar variable is effectively forming a memoization technique?
If not, how can I use memoization to improve the runtime performance of this algorithm?
You can use hash map for solving this problem with memorization (Ex: Guava Table)
Table<Integer, Integer, Integer> calculated = HashBasedTable.create();
private static int helper(int step, int sumSoFar, int[] nums, int target) {
if (step == nums.length) {
return sumSoFar == target ? 1 : 0;
}
if (calculated.contains(step, sumSoFar)) {
return calculated.get(step, sumSoFar)
}
int result = helper(step + 1, sumSoFar + nums[step], nums, target)
+
helper(step + 1, sumSoFar - nums[step], nums, target);
calculated.put(step, sumSoFar, result);
return result;
}
You probably want to achieve "memoization" with following algorithm. I have added one more parameter in recursion - rest which can be absolute positive or absolute negative sum of the non-seen elements. So it breaks recursion if there is no chance to reach the target.
With this approach, worst case is still O(2^n) - i.e. [0,0,0,0], but in practice it is faster.
Note: assumption is that elements in nums are positive, if not you can make them in O(n).
public static void main(String[] args) {
int[] nums = {1, 2, 3, 2};
int totalSumSum = arraySum(nums);
int x = helper(-1, 0, nums, 0, totalSumSum);
System.out.println(x);
}
private static int helper(int step, int sumSoFar, int[] nums, int target, int rest) {
if (step == nums.length-1) {
return sumSoFar == target ? 1 : 0;
}
int nextStep = step+1;
int nextSumPos = sumSoFar + nums[nextStep];
int nextSumNeg = sumSoFar - nums[nextStep];
int nextRest = rest - nums[nextStep];
boolean pos = false;
if ((nextSumPos > target && nextSumPos - nextRest > target) ||
(nextSumPos < target && nextSumPos + nextRest < target)) { /* do nothing */ }
else { pos = true; }
boolean neg = false;
if ((nextSumNeg > target && nextSumNeg - nextRest > target) ||
(nextSumNeg < target && nextSumNeg + nextRest < target)) { /* do nothing */ }
else { neg = true; }
if (pos && neg) {
return helper(nextStep, nextSumPos, nums, target, nextRest)
+ helper(nextStep, nextSumNeg, nums, target, nextRest);
}else if (pos && !neg) {
return helper(nextStep, nextSumPos, nums, target, nextRest);
} else if (!pos && neg) {
return helper(nextStep, nextSumNeg, nums, target, nextRest);
} else { /* !pos && !neg */
return 0;
}
}
private static int arraySum(int[] nums) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
return sum;
}
I'm trying to program a solution to the 3sum question on leetcode(link: https://leetcode.com/problems/3sum/).
This is what I've done so far:
public int binary_search(int [] nums, int start, int end, int target)
{
if (start > end)
{
return -1;
}
int mid = (start + end) / 2;
if (nums[mid] == target)
{
return mid;
}
else {
if (nums[mid] < target)
{
return binary_search(nums, mid + 1, end, target);
} else {
return binary_search(nums, start, mid - 1, target);
}
}
}
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
ArrayList<List<Integer>> solution_set = new ArrayList();
Set<List<Integer>> ordered_solutions = new HashSet();
for (int i = 0; i < nums.length; i++)
{
if (i + 1 == nums.length)
{
continue;
}
int number_1 = nums[i];
int number_2 = nums[i+1];
int target = -(number_1 + number_2);
int target_index = binary_search(nums, 0, nums.length - 1, target);
if (binary_search(nums, 0, nums.length - 1, target) != -1 && target_index != i && target_index != i+1)
{
List<Integer> submission = new ArrayList();
submission.add(number_1); submission.add(number_2); submission.add(target);
List<Integer> ordered_submission = submission;
Collections.sort(ordered_submission);
if (ordered_solutions.add(ordered_submission) == true)
{
solution_set.add(submission);
}
}
}
return solution_set;
}
The program works as follows:
input is given to function threeSum which is then sorted and two following objects are created; An ArrayList that will store all non-duplicate solutions and a Set that is used to test for said duplicate solutions.
Then, the for loop sifts through the array and does the following:
it adds the i and i+1 element then negates them to find the number needed to sum all three numbers to zero. With this number acquired, a binary search is conducted on the array to see if this number can be found. If it is found, a few other conditions are tested to ensure that the target index is not actually the same as index i or i+1. After that, I create two objects, a submission that includes the elements in their original order and an ordered submission. If the ordered submission is inserted into the set and the set returns true, it means it's not a duplicate and i store it in the solution_set.
My problem is as follows: My program fails with the test case [0,0,0]. I believe the target is calculated as zero, but the binary search chooses the zero which is in i+1 so the solution is rejected. Does anyone have any suggestions on how this problem can be fixed?
Ok, if you want to do it with binary search, here it is. I've fixed several logical bugs, made some improvements, and added some comments, hope this will help. The code is accepted by leetcode, but it is not so efficient solution. Time complexity is O(n^2*logn). With 2 pointers approach you can do it in O(n^2).
public int binary_search(int[] nums, int start, int end, int target) {
if (start > end) {
return -1;
}
int mid = (start + end) / 2;
if (nums[mid] == target) {
return mid;
} else {
if (nums[mid] < target) {
return binary_search(nums, mid + 1, end, target);
} else {
return binary_search(nums, start, mid - 1, target);
}
}
}
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
ArrayList<List<Integer>> solution_set = new ArrayList<>();
// you can't do it using only one loop.
// Take a look at this sample input -2,0,1,1,2.
// Here you have to consider for nums[i] and nums[j] -2, 0 as well as
// -2, 1
for (int i = 0; i < nums.length - 2; i++) {
// skip duplicates
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.length - 1; j++) {
int number_1 = nums[i];
int number_2 = nums[j];
// skip duplicates and, since array is sorted, don't need to
// consider values > 0
if (i != j - 1 && nums[j - 1] == nums[j] || number_1 + number_2 > 0)
continue;
int target = -(number_1 + number_2);
// since array is sorted, start binary search only from j + 1
int target_index = binary_search(nums, j + 1, nums.length - 1, target);
if (target_index != -1) {
List<Integer> submission = new ArrayList<>();
submission.add(number_1);
submission.add(number_2);
submission.add(target);
solution_set.add(submission);
}
}
}
return solution_set;
}
Output:
[[0, 0, 0]]
[[-2, 0, 2], [-2, 1, 1]]
[[-1, -1, 2], [-1, 0, 1]]
I am writing a program and I can't seem to make the IF action loop and check all of the arrays in the main. My job is to figure out whether there exists any pair of numbers (i.e., any two elements) in this ascending sorted array that will add up to 20. All you need to do is to sum the values these two pointers point to and see if they are equal to 20, if so, output. otherwise, inspect the sum, if the sum is greater than 20,decrement the second pointer and if the sum is less than 20, increment the first pointer. cannot use the nested for loop approach!! Not sure how to fix this... i've been at it for hours and have handwritten it with no luck. thank you!!
// if val of arr at index i is smaller than at arr j, then return
// smaller value
// This function will inspect the input to find any pair of values that
// add up to 20
// if it find such a pair, it will return the *index* of the smallest
// value
// if it does not find such as pair, it will return -1;
public class SumExperiment {
public static int check_sum(int[] array) {
int i = array[0];
int y = array.indexOf(array.length); // need value # index of array.length to begin
//loop to repeat action
for (int arraysChecked = 0; arraysChecked < 5; arraysChecked++ )
{
if ( i + y == 20)
{
return i;
// System.out.print(array[i]);
}
else if ( i + y > 20)
{
y--; //index #y
}
else if (i + y < 20)
{
i++; //index #x
}
if ( i + y != 20)
{
return -1;
}
arraysChecked++;
}
return -1; //because must return int, but this isn't correct
}
public static void main(String[] args) {
int[] array1 = new int[] { 5, 7, 8, 9, 10, 15, 16 };
if (check_sum(array1) != 0)
System.err.println("TEST1 FAILED");
int[] array2 = new int[] { 3, 5, 8, 9, 10, 15, 16 };
if (check_sum(array2) != 1)
System.err.println("TEST2 FAILED");
int[] array3 = new int[] { 3, 4, 6, 9, 10, 14, 15 };
if (check_sum(array3) != 2)
System.err.println("TEST3 FAILED");
int[] array4 = new int[] { 6, 7, 8, 9, 10, 15, 16 };
if (check_sum(array4) != -1)
System.err.println("TEST4 FAILED");
System.out.println("Done!!!");
}
}
I think you are getting confused between the values in the array and the indices of the values. Here is a working version with variable names that make it easier to understand what's going on:
public static int check_sum(int[] array) {
int leftIndex = 0;
int rightIndex = array.length - 1;
for (int arraysChecked = 0 ; arraysChecked < 5 ; arraysChecked++) {
if (leftIndex == rightIndex) {
return -1;
}
int smallerValue = array[leftIndex];
int largerValue = array[rightIndex];
int sum = smallerValue + largerValue;
if (sum == 20) {
// Returns INDEX of smaller value
return leftIndex;
} else if (sum > 20) {
rightIndex--;
} else if (sum < 20) {
leftIndex++;
}
// NO NEED FOR THIS: arraysChecked++; (for loop does it for you)
}
}
I'm studying the 3 Sum to implement it on my own, and came across the following implementation with the rules:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
And implementation (sorts the array, iterates through the list, and uses another two pointers to approach the target):
import java.util.*;
public class ThreeSum {
List<List<Integer>> threeSum(int[] num) {
Arrays.sort(num);
List<List<Integer>> res = new LinkedList<>();
for (int i=0; i<num.length-2; i++) {
if (i==0 || (i>0 && num[i] != num[i-1])) { //HERE
int lo = i+1;
int hi = num.length-1;
int sum = 0 - num[i];
while (lo < hi) {
if (num[lo] + num[hi] == sum) {
res.add(Arrays.asList(num[i], num[lo], num[hi]));
while (lo < hi && num[lo] == num[lo+1]) lo++; //HERE
while (lo < hi && num[hi] == num[hi-1]) hi--; //HERE
lo++; hi--;
} else if (num[lo] + num[hi] < sum) lo++;
else hi--;
}
}
}
return res;
}
//Driver
public static void main(String args[]) {
ThreeSum ts = new ThreeSum();
int[] sum = {-1, 0, 1, 2, -1, -4};
System.out.println(ts.threeSum(sum));
}
}
And my question is (located where commented: //HERE), what's the reason for checking num[i] != num[i-1], num[lo] == num[lo+1], and num[hi] == num[hi-1]? Supposedly they are supposed to skip the same result, but what does that mean? Examples would really help.
Thank you in advance and will accept answer/up vote.
Imagine you have {-1,-1,0,1,2,4} and considering triplet num[0], num[2], num[3] (-1,0,1).
lo=0 here. To exclude triplet num[1], num[2], num[3] with the same values, we should increment lo and pass over duplicate
This will prevent the list to have duplicate triplet.
For example, with you test :
int[] sum = {-1, 0, 1, 2, -1, -4};
will be sorted like :
sum = {-4, -1, -1, 0, 1, 2};
You see that you have -1 twice. Without these test, you would test twice if -1 = 0 + 1. This is not usefull so the algo simply search the next different value.
You could remove duplicate in the sorted List to prevent these test.
Thanks to MBo, we can't remove duplicate since we can have triplet with same value (but with different index)
All the three sentences is used to avoid the duplicate output.
Consider a sorted list {-2, -2 , 1, 1}
If there is no checking for num[i] != num[i-1], the output of the program would be(-2, 1, 1)and(-2, 1, 1), which are two duplicate triplets.
The checking for num[lo] != num[lo + 1]and num[hi] != num[hi - 1] are for the same reason.
Consider a sorted list
{-2,-1,-1,0,3}
If there is no checking for num[lo], you will get (-2,-1,3) and (-2,-1,3) as the output.
Still, I want to recommend a better solution for this problem. You can numerate the sum of two numbers in the list and find the 3rd number by hash or binary search. It will helps you to gain a O(n^2logn) time complexity rather than O(n^3). (I was wrong, the time complexity of this algorithm is O(n^2), sorry for that.)
Following program finds pairs of three integer with O(N*2)
Sort the input Array
and iterate each element in for loop and check for sum in program which is developed for Two sum.
Two sum in linear time after sorting ->
https://stackoverflow.com/a/49650614/4723446
public class ThreeSum {
private static int countThreeSum(int[] numbers) {
int count = 0;
for (int i = 0; i < numbers.length; i++) {
int front = 0, rear = numbers.length - 1;
while (front < rear) {
if (numbers[front] + numbers[rear] + numbers[i] == 0) {
System.out.printf(String.format("Front : {%d} Rear : {%d} I : {%d} \n", numbers[front],
numbers[rear], numbers[i]));
front++;
rear--;
count++;
} else {
if (Math.abs(numbers[front]) > Math.abs(numbers[rear])) {
front++;
} else {
rear--;
}
}
}
}
return count;
}
public static void main(String[] args) {
int[] numbers = { 1, 3, 5, 7, 12, 16, 19, 15, 11, 8, -1, -3, -7, -8, -11, -17, -15 };
Arrays.sort(numbers);
System.out.println(countThreeSum(numbers));
}
}
It's worked with any NSum (3Sum, 4Sum, 5Sum, ...) and quite fast.
public class ThreeSum {
private static final int RANDOM_RANGE = 20;
private Integer array[];
private Integer arrayIndex[];
private int result[];
private int bagLength;
private int resultIndex = 0;
private void generateData(int size) {
array = new Integer[size];
Random random = new Random();
for (int i = 0; i < size; i++) {
array[i] = random.nextInt(RANDOM_RANGE) - (RANDOM_RANGE/2);
}
}
private void markArrayIndex(int size) {
arrayIndex = new Integer[size];
for (int i = 0; i < size; i++) {
arrayIndex[i] = i;
}
}
private void prepareBeforeCalculate(int size, int sumExpected, int bagLength) {
this.bagLength = bagLength;
result = new int[bagLength];
generateData(size);
markArrayIndex(size);
}
void calculate(int size, int sumExpected, int bagLength) {
prepareBeforeCalculate(size, sumExpected, bagLength);
Arrays.sort(arrayIndex, (l, r) -> array[l].compareTo(array[r]));
System.out.println(Arrays.toString(array));
long startAt = System.currentTimeMillis();
if (sumExpected > 0) findLeft(sumExpected, 0, 0, array.length);
else findRight(sumExpected, 0, 0 - 1, array.length - 1);
System.out.println("Calculating in " + ((System.currentTimeMillis() - startAt) / 1000));
}
private void findLeft(int total, int indexBag, int left, int right) {
while (left < array.length && array[arrayIndex[left]] < 0 && indexBag < bagLength) {
navigating(total, arrayIndex[left], indexBag, left, right);
left++;
}
}
private void findRight(int total, int indexBag, int left, int right) {
while (right >= 0 && array[arrayIndex[right]] >= 0 && indexBag < bagLength) {
navigating(total, arrayIndex[right], indexBag, left, right);
right--;
}
}
private void navigating(int total, int index, int indexBag, int left, int right) {
result[indexBag] = index;
total += array[index];
if (total == 0 && indexBag == bagLength - 1) {
System.out.println(String.format("R[%d] %s", resultIndex++, toResultString()));
return;
}
if (total > 0) findLeft(total, indexBag + 1, left + 1, right);
else findRight(total, indexBag + 1, left, right - 1);
}
private String toResultString() {
int [] copyResult = Arrays.copyOf(result, result.length);
Arrays.sort(copyResult);
int iMax = copyResult.length - 1;
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(array[copyResult[i]]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
}
public class ThreeSumTest {
#Test
public void test() {
ThreeSum test = new ThreeSum();
test.calculate(100, 0, 3);
Assert.assertTrue(true);
}
}
Below code I have written by following the logic from Median of two sorted arrays (method - 2)
You can even see the code at Ideone.com
class MedianOfTwoArrays {
public static void main(String[] args) {
// Note: These are sorted arrays and are of equal length.
int[] array1 = {1, 12, 15, 26, 38};
int[] array2 = {2, 13, 17, 30, 45};
int median = getMedianOfTwoArrays(array1, array2);
System.out.println(median);
}
static int getMedianOfTwoArrays(int[] array1, int[] array2) {
int index1 = array1.length/2;
int index2 = array2.length/2;
int m1 = array1[index1];
int m2 = array2[index2];
if(m1 == m2) {
return m1;
} else {
return findMedian(array1, array2, 0, array1.length - 1, 0, array2.length - 1);
}
}
static int findMedian(int[] array1,
int[] array2,
int low1,
int high1,
int low2,
int high2) {
if((high1 - low1 + 1) == 2 && (high2 - low2 + 1) == 2) {
return (Math.max(array1[low1], array2[low2]) + Math.min(array1[high1], array2[high2]))/2;
}
int mid1 = (low1 + high1)/2;
int mid2 = (low2 + high2)/2;
int m1 = array1[mid1];
int m2 = array2[mid2];
int low1_t = 0;
int high1_t = 0;
int low2_t = 0;
int high2_t = 0;
if(m1 == m2) {
return m1;
} else if(m1 > m2) {
low1_t = low1;
high1_t = mid1;
low2_t = mid2;
high2_t = high2;
return findMedian(array1, array2, low1_t, high1_t, low2_t, high2_t);
} else {
low1_t = mid1;
high1_t = high1;
low2_t = low2;
high2_t = mid2;
return findMedian(array1, array2, low1_t, high1_t, low2_t, high2_t);
}
}
}
It does not work for input arrays like,
int[] array1 = {1, 5, 17, 20}; // median is 10
int[] array2 = {4, 8, 13, 19};
int[] array1 = {1, 3, 5, 7, 9, 11}; // median is 6
int[] array2 = {2, 4, 6, 8, 10, 12};
The problem as per my analysis is, the termination condition. Some how the logic suggessted from geeksforgeeks seems to be having some issue with the termination condition.
(Math.max(array1[low1], array2[low2]) + Math.min(array1[high1], array2[high2]))/2;
But I could not able to solve it and make it work for the above inputs.
Can someone please look into this issue and let me know where am I making mistake?
Your main error is that when you do plain int mid1 = (low1 + high1)/2; your mid1 is always shifted to the left, and then you assign mid1 without taking this shift into account, therefore each nested comparison compares elements of arrays that are shifted left from the intended position, and since median of an array of length 2n is always a[n-1]+a[n]/2, you are comparing wrong elements of arrays after the first performed comparison. You seemingly incorrently implemented this block of Method 2's code:
if (n % 2 == 0)
return getMedian(ar1 + n/2 - 1, ar2, n - n/2 +1);
else
return getMedian(ar1 + n/2, ar2, n - n/2);
In fact, the simple assert (high2-low2==high1-low1) at the entrance to findMedian() would alert you of incorrect logic, since with arrays of size 4 the second entrance yields unequal array sizes. The exit condition is pretty fine, as it's directly copied from Method 2's code. Therefore, you need to change the block of assigning low1_t and others to the following:
assert (high2-low2==high1-low1); // sanity check
int n=high1-low1+1; // "n" from logic
int m1 = median(array1,low1,high1);
int m2 = median(array2,low2,high2);
int low1_t = low1;
int high1_t = high1;
int low2_t = low2;
int high2_t = high2;
if(m1 == m2) {
return m1;
} else if(m1 > m2) {
if (n % 2 == 0) {
high1_t = high1-n/2+1;
low2_t = low2+n/2-1;
} else {
high1_t = high1-n/2;
low2_t = low2+n/2;
}
} else {
if (n % 2 == 0) {
low1_t = low1+n/2-1;
high2_t = high2-n/2+1;
} else {
low1_t = low1+n/2;
high2_t = high2-n/2;
}
}
return findMedian(array1, array2, low1_t, high1_t, low2_t, high2_t);
And add function median like this:
static int median(int[] arr, int low,int hig)
{
if ((low+hig)%2 == 0) return arr[(low+hig)/2];
int mid=(low+hig)/2;
return (arr[mid]+ arr[mid-1])/2;
}
Complete example (alter arrays as necessary): http://ideone.com/zY30Vg
This is a working code and it should solve your problem :-
public static void main(String[] args)
{
int[] ar1 = {1, 3, 5, 7, 9, 11};
int[] ar2 = {2, 4, 6, 8, 10, 12};
System.out.println((int) findMedianSortedArrays(ar1,ar2));
}
public static double findMedianSortedArrays(int A[], int B[]) {
int m = A.length;
int n = B.length;
if ((m + n) % 2 != 0) // odd
return (double) findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1);
else { // even
return (findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1)
+ findKth(A, B, (m + n) / 2 - 1, 0, m - 1, 0, n - 1)) * 0.5;
}
}
public static int findKth(int A[], int B[], int k,
int aStart, int aEnd, int bStart, int bEnd) {
int aLen = aEnd - aStart + 1;
int bLen = bEnd - bStart + 1;
// Handle special cases
if (aLen == 0)
return B[bStart + k];
if (bLen == 0)
return A[aStart + k];
if (k == 0)
return A[aStart] < B[bStart] ? A[aStart] : B[bStart];
int aMid = aLen * k / (aLen + bLen); // a's middle count
int bMid = k - aMid - 1; // b's middle count
// make aMid and bMid to be array index
aMid = aMid + aStart;
bMid = bMid + bStart;
if (A[aMid] > B[bMid]) {
k = k - (bMid - bStart + 1);
aEnd = aMid;
bStart = bMid + 1;
} else {
k = k - (aMid - aStart + 1);
bEnd = bMid;
aStart = aMid + 1;
}
return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}