Google Foobar Numbers Station - java

Im trying to solve a google foobar challenge but I am stuck on how to change this to use recursion. any pointers would be helpful
public static int[] answer(int[] l, int t) {
// convert the array into a list
List<Integer> list = new ArrayList<>();
for (int i : l) {
list.add(i);
}
for (int i = 0; i < list.size(); i++) {
Integer n = list.get(i);
if (i >= 1) {
Integer nMinus1 = list.get(i - 1);
Integer nMinus2;
Integer nMinus3;
Integer nMinus4;
Integer nMinus5;
Integer nMinus6;
if (n + nMinus1 == t) {
// done
return new int[]{i - 1, i};
} else if (i >= 2) {
nMinus2 = list.get(i - 2);
if (n + nMinus1 + nMinus2 == t) {
// done
return new int[]{i - 2, i};
} else if (i >= 3) {
nMinus3 = list.get(i - 3);
if (n + nMinus1 + nMinus2 + nMinus3 == t) {
// done
return new int[]{i - 3, i};
} else if (i >= 4) {
nMinus4 = list.get(i - 4);
if (n + nMinus1 + nMinus2 + nMinus3 + nMinus4 == t) {
// done
return new int[]{i - 4, i};
} else if (i >= 5) {
nMinus5 = list.get(i - 5);
if (n + nMinus1 + nMinus2 + nMinus3 + nMinus4 + nMinus5 == t) {
// done
return new int[]{i - 5, i};
} else if (i >= 6) {
nMinus6 = list.get(i - 6);
if (n + nMinus1 + nMinus2 + nMinus3 + nMinus4 + nMinus5 + nMinus6 == t) {
// done
return new int[]{i - 6, i};
}
}
}
}
}
}
}
}
return new int[]{-1, -1};
}
Here is the question:
Given the list l as [4, 3, 5, 7, 8] and the key t as 12, the function answer(l, t) would return the list [0, 2] because the list l contains the sub-list [4, 3, 5] starting at index 0 and ending at index 2, for which 4 + 3 + 5 = 12, even though there is a shorter sequence that happens later in the list (5 + 7). On the other hand, given the list l as [1, 2, 3, 4] and the key t as 15, the function answer(l, t) would return [-1, -1] because there is no sub-list of list l that can be summed up to the given target value t = 15.

You probably don't need an arraylist. You could perform a double loop on the array l. Why do you want recursion?
You could do something like:
public static int[] answer(int[] l, int t) {
int[] rets = {-1, -1};
int sum=0;
for (int i=0; i<l.length; i++) {
sum=0;
for (int j=i; j<l.length; j++) {
sum+=l[j];
if (sum > t) break;
if (sum == t) {
rets[0] = i;
rets[1] = j;
return rets;
}
}
}
return rets;
}

Just submitted my solution.. it got accepted, so I know it was accepted by Google:
(I believe this will be slightly faster than above solution since it will break the loops and return if the target is greater than sum of all numbers in the array.)
public static int[] answer(int[] l, int t){
int sum =0;
List<Integer> indexes = new ArrayList<>();
for(int j=0;j<l.length;j++){
sum = 0;
indexes.clear();
for(int i=j;i<l.length;i++){
sum += l[i];
indexes.add(i);
if(sum >= t){
break;
}
}
if(sum == t){
break;
}
else if(sum > t){
continue;
}
else{
return new int[] {-1,-1};
}
}
int[] returnArray = new int[2];
if(indexes.size()>0){
returnArray[0] = indexes.get(0);
returnArray[1] = indexes.get(indexes.size()-1);
}
return returnArray;
}

Related

insertion sort is not outputting right

My condition is not outputting the right numbers, the list is not changed trough the loop, this is my condition.
if (j + 1 <= length)
{
insertionSort(arrayIn, indexIn + 1);
}
}
The condition for the recursive call:
if (j + 1 <= length)
is wrong.
You should make the recursive call as long as indexIn is smaller than the last index of the array:
if (indexIn < length - 1) {
insertionSort(arrayIn, indexIn + 1);
}
The rest of your code is fine.
You could try this:
public static void insertionSort(int arrayIn[], int indexIn) {
if (indexIn <= 1)
return;
insertionSort(arrayIn, indexIn - 1);
int last = arrayIn[indexIn - 1];
int j = indexIn - 2;
while (j >= 0 && arrayIn[j] > last) {
arrayIn[j + 1] = arrayIn[j];
j--;
}
arrayIn[j + 1] = last;
}
public static void main(String[] args){
int[] array = {1, 3, 2, 4};
insertionSort(array, array.length);
for (int i = 0; i < array.length; i++){
System.out.print(array[i] + " ");
}
}
I could a ArrayIndexOutOfBound operation, in your code,
Instead of,
if (j + 1 <= length)
{
insertionSort(arrayIn, indexIn + 1);
}
Use this,
if (j + 1 < length)
{
insertionSort(arrayIn, indexIn + 1);
}
And you have print your content of your array too,
public static void main(String[] args) {
int[] arr = new int[]{2, 3, 4, 1, 5};
insertionSort(arr, 0);
for(int i : arr)
{
System.out.print(i + " ");
}
}
Output:
1 2 3 4 5

How do i make it so every number that is next to a zero divides by two?

Everything I have tried so far divides the code by 2 and it does it twice for some reason.
CSP-ARRAY
An array inhabitant represents cities and their respective populations. For example, the following arrays shows 8 cities and their respective populations:[3, 6, 0, 4, 3, 2, 7, 1]Some cities have a population of 0 due to a pandemic zombie disease that is wiping away the human lives. After each day, any city that is adjacent to a zombie-ridden city will lose half of its population.Write a program to loop though each city population and make it lose half of its population if it is adjacent (right or left) to a city with zero people until all cities have no humans left.
package Arrays;
public class Project {
public static void main(String[] args){
int i = 0;
boolean hi = false;
boolean hi1 = false;
boolean hi2 = false;
boolean hi3 = false;
boolean hi4 = false;
boolean hi5 = false;
boolean hi6 = false;
boolean hi7 = false;
int[] a = {3, 6, 0, 4, 3, 2, 7, 1};
if(a[0]==0) {
hi=true;
}
if(a[1]==0) {
hi1=true;
}
if(a[2]==0) {
hi2=true;
}
if(a[3]==0) {
hi3=true;
}
if(a[4]==0) {
hi4=true;
}
if(a[5]==0) {
hi5=true;
}
if(a[6]==0) {
hi6=true;
}
if(a[7]==0) {
hi7=true;
}
int z=1;
while(hi!=false || hi1!=false || hi2!=false || hi3!=false || hi4!=false || hi5!=false || hi6!=false || hi7!=false) {
if(hi=true){
a[1]=a[1]/2;
}
if(hi1=true){
a[0]=a[0]/2;
a[2]=a[2]/2;
}
if(hi2=true){
a[1]=a[1]/2;
a[3]=a[3]/2;
}
if(hi3=true){
a[2]=a[2]/2;
a[4]=a[4]/2;
}
if(hi4=true){
a[3]=a[3]/2;
a[5]=a[5]/2;
}
if(hi5=true){
a[4]=a[4]/2;
a[6]=a[6]/2;
}
if(hi6=true){
a[5]=a[5]/2;
a[7]=a[7]/2;
}
if(hi7=true){
a[6]=a[6]/2;
}
System.out.println("Day "+i+": ["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+"] ");
i++;
}
}
}
I think it is pretty simple. Just go through the array and check previous and next value.
public static void calc(int[] arr) {
for(int i = 1; i < arr.length; i++)
if(arr[i] > 0 && arr[i - 1] == 0)
arr[i] /= -2;
for(int i = arr.length - 2; i >= 0; i--)
if(arr[i] < 0)
arr[i] = -arr[i];
else if(arr[i] > 0 && arr[i + 1] == 0)
arr[i] /= 2;
}
I am also new to Java, but here is my attempt.
import java.util.Arrays;
public class Project {
public static void main(String[] args) {
int[] a = {3, 6, 0, 4, 3, 2, 7, 1};
zombieApocalypse(a);
}
public static void zombieApocalypse(int[] array) {
boolean keepGoing = true;
int j = 1;
while (keepGoing) {
int[] arrayCopy = array;
//first element
if (array[0] == 0) {
arrayCopy[1] = array[1] / 2;
}
//element in the middle
for (int i = 1; i < array.length - 1; i++) {
if (array[i] == 0) {
arrayCopy[i - 1] = array[i - 1] / 2;
arrayCopy[i + 1] = array[i + 1] / 2;
}
}
//last element
if (array[array.length - 1] == 0) {
arrayCopy[array.length - 1] = array[array.length - 1] / 2;
}
System.out.println("Day " + j);
//copies clone back to original array
array = arrayCopy;
System.out.println(Arrays.toString(array));
j++;
int counter = 0;
//for each element checking if every city is zero
for (int element : array) {
counter = counter + element;
}
//if each element value in every city is zero, we stop
if (counter == 0) {
keepGoing = false;
}
}
}
}
This is what you were going for.
import java.util.Arrays;
public class Project {
public static void main(String[] args) {
int i = 0;
boolean hi = false;
boolean hi1 = false;
boolean hi2 = false;
boolean hi3 = false;
boolean hi4 = false;
boolean hi5 = false;
boolean hi6 = false;
boolean hi7 = false;
int[] a = {3, 6, 0, 4, 3, 2, 7, 1};
//the line of code below this comment is never used ever, what is it for?
int z = 1;
while ((((!hi || !hi1) || (!hi2 || !hi3)) || (!hi4 || !hi5)) || (!hi6 || !hi7)){
if (hi) {
a[1] = a[1] / 2;
}
if (hi1) {
a[0] = a[0] / 2;
a[2] = a[2] / 2;
}
if (hi2) {
a[1] = a[1] / 2;
a[3] = a[3] / 2;
}
if (hi3) {
a[2] = a[2] / 2;
a[4] = a[4] / 2;
}
if (hi4) {
a[3] = a[3] / 2;
a[5] = a[5] / 2;
}
if (hi5) {
a[4] = a[4] / 2;
a[6] = a[6] / 2;
}
if (hi6) {
a[5] = a[5] / 2;
a[7] = a[7] / 2;
}
if (hi7) {
a[6] = a[6] / 2;
}
System.out.println("Day " + i + Arrays.toString(a));
i++;
/*if you want to update the boolean values after they are changed, then you have to include it within the block of code
that is changing it. (if they are outside of this block of code, how will they ever update?)
*/
if (a[0] == 0) {
hi = true;
}
if (a[1] == 0) {
hi1 = true;
}
if (a[2] == 0) {
hi2 = true;
}
if (a[3] == 0) {
hi3 = true;
}
if (a[4] == 0) {
hi4 = true;
}
if (a[5] == 0) {
hi5 = true;
}
if (a[6] == 0) {
hi6 = true;
}
if (a[7] == 0) {
hi7 = true;
}
}
}
}
For each day iteration, you find the cities that have 0 population and push those indices to an array and let's name this array "indices". Then loop through this array and divide the population half only neighbor of these indices. I write in javascript.
const inhabitants = (Arr) => {
let day = 0;
let A = Arr;
// allEqual checks if the all elements in array is 0
// when allEqual is true loop is over
const allEqual = (arr) => arr.every((v) => v === arr[0]);
while (!allEqual(A)) {
// find the array[i]= 0 and push the "i" in indices
let indices = [];
for (let i = 0; i < A.length; i++) {
if (A[i] === 0) {
indices.push(i);
}
}
// just divide the neighbor elements of element 0
for (let j = 0; j < indices.length; j++) {
if (indices[j] > 0) {
A[indices[j] - 1] = Math.floor(A[indices[j] - 1] / 2);
}
if (indices[j] + 1 < A.length) {
A[indices[j] + 1] = Math.floor(A[indices[j] + 1] / 2);
}
}
day++;
console.log(`population on day ${day}`, A);
}
};

Java: How to implement 3 sum?

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);
}
}

Find elements in array whose sum is equal to 10 - Java

I want to find all the pairs of numbers from an array whose sum is equal to 10, and am trying to improve upon this bit of code here:
for (int j = 0; j < arrayOfIntegers.length - 1; j++)
{
for (int k = j + 1; k < arrayOfIntegers.length; k++)
{
int sum = arrayOfIntegers[j] + arrayOfIntegers[k];
if (sum == 10)
return j + "," + k;
}
}
However, I'm having trouble moving through the array. Here's what I have so far:
int[] arrayOfIntegers = {0, 5, 4, 6, 3, 7, 2, 10};
Arrays.sort(arrayOfIntegers);
System.out.println(Arrays.toString(arrayOfIntegers));
int left = arrayOfIntegers[0];
int right = (arrayOfIntegers[arrayOfIntegers.length - 1]);
while (left < right)
{
int sum = left + right;
if (sum == 10) //check to see if equal to 10
{
System.out.println(left + "," + right);
}
if (sum > 10) // if sum is more than 10, move to lesser number
{
right --;
}
if (sum < 10) // if sum is less than 10, move to greater number
{
left++;
}
} // end of while
Try this code by passing the value of the sum and array in which you want to find the pair of elements equals to a given sum using one for loop
private void pairofArrayElementsEqualstoGivenSum(int sum,Integer[] arr){
List numList = Arrays.asList(arr);
for (int i = 0; i < arr.length; i++) {
int num = sum - arr[i];
if (numList.contains(num)) {
System.out.println("" + arr[i] + " " + num + " = "+sum);
}
}
}
You need to capture the values as well as the indexes:
int[] arrayOfIntegers = {0, 5, 4, 6, 3, 7, 2, 10};
Arrays.sort(arrayOfIntegers);
System.out.println(Arrays.toString(arrayOfIntegers));
int left = 0;
int right = arrayOfIntegers.length - 1;
while (left < right)
{
int leftVal = arrayOfIntegers[left];
int rightVal = (arrayOfIntegers[right]);
int sum = leftVal + rightVal;
if (sum == 10) //check to see if equal to 10
{
System.out.println(arrayOfIntegers[left] + "," + arrayOfIntegers[right]);
right --;
left++;
}
if (sum > 10) // if sum is more than 10, move to lesser number
{
right --;
}
if (sum < 10) // if sum is less than 10, move to greater number
{
left++;
}
} // end of while
output:
[0, 2, 3, 4, 5, 6, 7, 10]
0,10
3,7
4,6
This is sample code with javascrypt. Someone can use it
var arr = [0, 5, 4, 6, 3, 7, 2, 10]
var arr1 = arr;
for(var a=0; a<arr.length;a++){
for(var b=0; b<arr.length; b++){
if(arr[a]+arr[b]===10 && a!==b){
console.log(arr[a]+" + "+arr[b])
arr.splice(a,1);
}
}
}
Java - Using single loop
public static void findElements() {
List<Integer> list = List.of(0, 5, 4, 6, 3, 7, 2, 10);
for (int i = 0; i < list.size(); i++) {
int sum = 0;
if (i < list.size() - 1) {
sum = list.get(i) + list.get(i + 1);
if (sum == 10) {
System.out.println("Element: " + list.get(i) + "," + list.get(i + 1));
}
} else {
if (list.get(i) == 10) {
System.out.println("Element: " + list.get(i));
}
}
}
}

Median of two sorted arrays : Termination condition failing

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);
}

Categories