Calculating max value of paths inside of 2D int array using recursion - java

I was given an assignment and we are only allowed to use recursive methods to solve different problems given to us.
I'm fairly new to programming and I'm having a hard time wrapping my head around it.
One of the objectives in the assignment is to calculate the max value of all possible paths in any given 2D integer array. Basically what this means is that when given a 2D int array, I need to use recursion to go through all different paths (abiding to the rules of only moving one element down or one element to the right at a time) in the array and return the value of the path with the highest sum value of elements in that path.
For example: (just a random example, could be any 2D int array with no particular order or size)
int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}};
the output should be: '48' (1 + 5 + 9 + 10 + 11 + 12)
This is what I have so far (but I have a feeling I'm way off):
public static int maxVal(int[][] arr) {
return maxVal(arr, 0, 0);
} // end of method
// Returns the value of the maximal path in the
// given 2D array, starting at location (i,j)
private static int maxVal(int[][] arr, int i, int j) {
// terminates when reaches last element
if ((i + 1) == arr.length && (j + 1) == arr[0].length) {
return 0;
} else {
// if the elemnt is at the last column
if ((i + 1) == arr.length) {
return maxVal(arr, i, j) + arr[i][j - 1];
// if element is at the last row
} else if ((j + 1) == arr[0].length) {
return maxVal(arr, i, j) + arr[i - 1][j];
} else {
return maxVal(arr, i, j) + arr[i - 1][j - 1];
}
}
}
I keep getting a StackOverFlowError. Any suggestions would be very helpful.

If you look closely, you will see that you are calling the same method over and over again return maxVal(arr, i, j), this will cause the SOF exception because there will be infi recursion calls since nothing is changing that will trigger the base cases.
You should instead return the current value added to the max value of the right/bottom.
private static int maxVal(int[][] arr, int i, int j)
{
if (i >= arr.length || i < 0 || j >= arr[i].length || j < 0) return 0;
int right = maxVal(arr, i, j + 1);
int bottom = maxVal(arr, i + 1, j);
return arr[i][j] + Math.max(right, bottom);
}
Try not to get lost in the recursion rabbit hole, instead set the correct base case which is once you reach an invalid i or j, you should just return 0 (end of current path)
if (i >= arr.length || i < 0 || j >= arr[i].length || j < 0) return 0;
if both indicies are valid, you will then have to recursively calculate the right and bottom values until it eventually reaches the end of the path (invalid indicies)
After that's done you will have two values, that are the result of the max sum of possible paths from your current right and current bottom, then you add your current value to the max value (right/bottom) and return it.

Related

Problem with a Java program that counts number of non self-intersecting paths between upper left to bottom right of a square array

It is well known that when one is allowed only to move right and down, the number of paths between the upper left cell to the bottom right cell of a rectanglular grid with side lengths n,m is the binomial coefficient n+m on n. I tried to think, at first in a mathematical manner, about the number of such paths when one is also allowed to move left and up; obviously the only way to give meaningful answer to such a question is to count non self-intersecting paths that do not go outside the rectangle (without those restrictions, the number of paths is infinite)
Since I had no idea how to count the number of such paths combinatorially, I wrote a java program that counts such paths and prints the paths, which I restricted to square arrays. However, already in an array of size 3x3, the program prints only 9 paths, while checking the number of such paths manually gave 12 paths. Here is the program:
public class pathCalculator {
public static int pathsCalculator(boolean[][] arr) {
return pathsCalculator(arr, 0, 0, "");
}
public static int pathsCalculator(boolean[][] arr, int i, int j, String s) {
if (i < 0 || i > arr.length - 1 || j < 0 || j > arr[0].length - 1) {
return 0;
} else if (arr[i][j] == false) {
return 0;
}
if (i == arr.length - 1 && j == arr[0].length - 1) {
s = s + "[" + (arr.length - 1) + "," + (arr.length - 1) + "]";
System.out.println(s);
return 1;
} else {
arr[i][j] = false;
s = s + "[" + i + "," + j + "]";
boolean[][] arr1 = new boolean[arr.length][arr.length];
for (int n = 0; n <= arr.length - 1; n++) {
for (int m = 0; m <= arr.length - 1; m++) {
arr1[n][m] = arr[n][m];
}
}
return pathsCalculator(arr1, i + 1, j, s) + pathsCalculator(arr1, i - 1, j, s) + pathsCalculator(arr1, i, j + 1, s) + pathsCalculator(arr1, i, j - 1, s);
}
}
}
The boolean array that is checked is initialized in the main program to be a square of "true"'s.
The main ideas of the program are therefore:
Recursion - each time the method calls to four variations of itself, which correspond to the four possibilies of: moving down,up,right and left.
Flagging forbidden cells - each time the path approaches a given cell, the program changes the cell's boolean value from true to false. The second if condition causes the program to return 0 in case we arrived at a forbidden cell (this indicates the path is self-intersecting).
Creating copies of the original boolean array - to prevent the different paths from interacting with each other on the same board, in each recursive step the previous boolean array values are copied into a new array.
So what is the problem with what I wrote? why it counts only a part of the total number of paths?
A minor change in the program, but of critical importance, enables the program to return the correct number of non self-intersecting paths bewteen the upper left cell to bottom right cell. In the coping part of the code, just before the recursive call, one should initialize 4 arrays instead of one, each of which is an identical copy of the previous array, and then let each of the four calls of pathscalculator method continue with a different copy of the array.
Here is the corrected version of the program:
public class pathCalculator{
public static int pathsCalculator(boolean[][] arr)
{
return pathsCalculator(arr,0,0,"");
}
public static int pathsCalculator(boolean [][] arr, int i, int j,String s)
{
if(i<0||i>arr.length-1||j<0||j>arr[0].length-1)
{
return 0;
}
else if(arr[i][j]==false)
{
return 0;
}
if(i==arr.length-1&&j==arr[0].length-1)
{
s = s+"["+(arr.length-1)+","+(arr.length-1)+"]";
System.out.println(s);
return 1;
}
else
{
arr[i][j]=false;
s = s+"["+i+","+j+"]";
boolean[][] arr1 = new boolean[arr.length][arr.length];
boolean[][] arr2 = new boolean[arr.length][arr.length];
boolean[][] arr3 = new boolean[arr.length][arr.length];
boolean[][] arr4 = new boolean[arr.length][arr.length];
for(int n=0;n<=arr.length-1;n++){
for(int m=0;m<=arr.length-1;m++){
arr1[n][m]=arr[n][m];
arr2[n][m]=arr[n][m];
arr3[n][m]=arr[n][m];
arr4[n][m]=arr[n][m];
}
}
return pathsCalculator(arr1,i+1,j,s)+pathsCalculator(arr2,i-1,j,s)+pathsCalculator(arr3,i,j+1,s)+pathsCalculator(arr4,i,j-1,s);
}
}
}
Here is the main function:
public class pathCalculatorTester
{
public static void main(String[] args)
{
boolean[][] arr ={{true,true,true},{true,true,true}
,{true,true,true}};
System.out.println(pathCalculator.pathsCalculator(arr));
}
}
And this is the output:
[0,0][1,0][2,0][2,1][1,1][0,1][0,2][1,2][2,2]
[0,0][1,0][2,0][2,1][1,1][1,2][2,2]
[0,0][1,0][2,0][2,1][2,2]
[0,0][1,0][1,1][2,1][2,2]
[0,0][1,0][1,1][0,1][0,2][1,2][2,2]
[0,0][1,0][1,1][1,2][2,2]
[0,0][0,1][1,1][2,1][2,2]
[0,0][0,1][1,1][1,2][2,2]
[0,0][0,1][1,1][1,0][2,0][2,1][2,2]
[0,0][0,1][0,2][1,2][2,2]
[0,0][0,1][0,2][1,2][1,1][2,1][2,2]
[0,0][0,1][0,2][1,2][1,1][1,0][2,0][2,1][2,2]
12
It returns the correct number of paths for 3x3 square, but since I don't have full understanding why it was nessecary to initialize 4 arrays insted of one, I'm not sure it works well for larger arrays. By the way, the function f(n) where n is the length size of the square and f is the number of paths, appears to grow amazingly fast - for 4x4 squares the number of paths that the program returned is 184, and for 5x5 squares the number is 8512.

Recursive method to replace all occurrences of a value in a 2D array

I have created a recursive method that replaces all occurrences of an element in a two dimensional double array. The issue is that I cannot seem to get this working without encountering a stack overflow error. Could someone please look at my code below and show me how to fix this? I have tried setting this up several times over the past few days. Thank you. Note that my arrays are 2 x 3, so the first if means that if you are at column 1 row 2, you are at the end of the array, and in that case you are done searching.
private static int replaceAll(double number, double replacementTerm) {
int i = 0;
int j = 0;
double searchFor = number;
double replace = replacementTerm;
if (i == 1 && j == 2) {
System.out.println("Search complete!");
}
if (twoDimArray2[i][j] == searchFor) {
System.out.println("Replaced An Element!");
twoDimArray2[i][j] = replace;
System.out.println(twoDimArray2[i][j]);
j++;
return replaceAll(searchFor, replace);
}
if (j == twoDimArray2.length) {
i++;
return replaceAll(searchFor, replace);
} else {
j++;
return replaceAll(searchFor, replace);
}
}
i and j should be method parameters instead of local variables so changes to their values can be tracked. Try to move right and down recursively if it does not exceed the bounds of the array. Note that this is much less efficient that iteration with two layers of for loops, as it will check multiple positions in the array more than once; to mitigate this, one can use a visited array to store all positions previous visited so they will not be checked again. See the below code in action here.
private static void replaceAll(double number, double replacementTerm, int i, int j) {
double searchFor = number;
double replace = replacementTerm;
if (twoDimArray2[i][j] == searchFor) {
System.out.println("Replaced An Element!");
twoDimArray2[i][j] = replace;
System.out.println(twoDimArray2[i][j]);
}
if (i == twoDimArray2.length - 1 && j == twoDimArray2[0].length - 1) {
System.out.println("Reached the end!");
return;
}
if (i + 1 < twoDimArray2.length) {
replaceAll(number, replacementTerm, i + 1, j);
}
if (j + 1 < twoDimArray2[0].length) {
replaceAll(number, replacementTerm, i, j + 1);
}
}

Backtracking - Given a set of numbers, find all the subsets with a sum equal to M (M is given)

As the title says, we are given a set of numbers and we have to find all the subsets with a sum equal to a given number(we'll call it M).
Most of you are probably familiar with the problem already, so let's cut to the chase. I have just recently gotten into backtracking programing (I gotta tell you that I'm a complete bust so far), that's why I am trying to solve the more "classic" problems.
Now, down below you will see my code that tries to solve this problem, in a backtracking fashion. However, the code gives
Exception in thread "main" java.lang.StackOverflowError
on line 44(I shall have it highlighted) and also, I don't really know if it really solves the problem in a backtracking way or if my code is just complete and utter poop.
package project3;
import java.util.*;
public class Main {
static int[] A = { 1, 2, 3, 4 }; // the array in which we are given the numbers.->
static int n = A.length; // -> I have it filled with 1, 2, 3, 4 for testing purposes
static int m = 5; // the number which the subsets' sum must be
static int[] Sol = new int[50]; // the array in which solutions are stored up->
//->until they are syso'ed, after that it gets zero'ed
static void makeZero() { // make the solution array 0 again
for (int i = 0; i < 50; i++)
Sol[i] = 0;
}
static void show() { // outputs the solution array
int i = 0;
while (Sol[i] != 0 && i < 49) {
System.out.print(Sol[i] + " ");
i++;
}
}
public static void main(String[] args) {
Sol[0]=A[0]; back(0, 1, A[0], 1);// we start with the first number in the array as->
} // -> both the first element as the solution and part of the sum
static int back(int i, int j, int S, int nr) {
if (i < n && j < n) {
if (A[j] + S == m) {// if we got a solution, we output it and then go to the ->
Sol[nr] = A[j]; // -> next element if possible, if not, we start again with ->
show(); // -> the following element
if (j < n - 1)
back(i, j++, S, nr);
else if (i < n - 1) {
makeZero();
back(i + 1, i + 2, 0, 0);
}
}
else if (A[j] + S > m) { // condition for stoping and starting over with another element
if (j < n - 1) // we try again with the following element
back(i, j++, S, nr);// LINE 44 : Exception in thread "main" java.lang.StackOverflowError
else if (i < n - 2 && j == n - 1) { // if not possible, we start again with the following element
makeZero();
back(i + 1, i + 2, 0, 0);
} else if (i == n - 2 && j == n - 1) // if we are down to the last element->
if (A[i + 1] == m) // ->we check if it is ==m
System.out.println(A[i + 1]);
}
else if (j < n - 1 && A[j] + S < m) { // obvious
Sol[nr++] = A[j];
S = S + A[j];
back(i, j + 1, S, nr);
}
else if (j == n - 1 && A[j] + S < m && i < n - 2) {// if the sum!=m and the are no more elements->
makeZero(); // ->start again with another element
back(i + 1, i + 2, 0, 0);
}
else { // if we are down to the last element, we check if it is ==m
if(A[i+1]==n-1)
System.out.println(A[i + 1]);
}
}
return 0;
}
}
NOTE: I hope that my comments are useful, but if they are more confusing than helping just ignore them, I think that you can get an idea of what I'm doing without them.
Nevertheless, I would like to find out why is it that the codes gives that error(I do know under what context that error is generally given, I do not understand however why I get it here, as I can't see any endless loop) and how to make the code work, and also whether or not it is backtracking.
In order to find all the subsets without reaching a stack overflow error I would highly recommend staying clear of recursion. Using recursion will typically generate a lot of overhead during runtime. This overhead tneds to lead to stack overflow errors. You should use a more stable algorithmic approach/design called dynamic programming.
Dynamic Programming Example should show you how to take what you currently have and translate it to the dynamic programming concept.

Finding peak values from an array in a given range

The method getPeakCount takes an int array and a range (int) as an input and returns the number of integers that are greater than all the elements to either side for the given range.
For example, consider an array {1,4,2,6,4,5,10,8,7,11} and range 2. The result should be 3, as {..,4,2,6,4,5,..}, {..,4,5,10,8,7,..} and {..,8,7,11} satisfy this condition. These satisfy the condition because 6, 10 and 11 are all greater than the 2 elements to both their left and right.
Note that for the the corner elements like 1 and 11, there's no need to check the left and right side respectively.
My code is below, but it is not correct.
static int getPeakCount(int[] arr, int R) {
int result=0;
for(int i=0;i<arr.length;i++){
if(i==0){
if(arr[i]>arr[i+1]&&arr[i]>arr[i+2]){
result++;
}
} //-----> closing if(i==0) condition
else if(i==arr.length-1){
if(arr[i]>arr[i-1]&&arr[i]>arr[i-2]){
result++;
}
}
else if(i+R>arr.length){
if(arr[i]>arr[i-R] && arr[i]>arr[i-R+1]){
System.out.println(arr[i]);
result++;
}
}
else{
if(arr[i]>arr[i+1] && arr[i]>arr[i+2] && arr[i]>arr[i-R] && arr[i]>arr[i-R+1]){
System.out.println(arr[i]);
result++;
}
}
}
return result;
}
I don't know whether I'm going in the right direction or not, and for last if condition it's throwing an java.lang.ArrayIndexOutOfBoundsException.
P.S. Don't consider this code as solution to remove errors from this. This is just the attempt I tried.
I think the right idea, and devnull is right. You just need to check the center, so change the loop to start at 1 and end 1 before the end. I commented out the end conditions. I think this does what you were asking, though not 100% sure I understood what you were after.
I should add, I use variables like l (left), r (right) and c (center) for clarity. You can make this much faster if you have large arrays. There is also redundancy in that it checks conditions it should know are already false (if I find a peak, I should skip the next value, as it can't also be a peak).
public class PeakChecker {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
int[] array = new int[]{1, 4, 2, 6, 4, 5, 10, 8, 7, 11};
System.out.println(nPeaks(array, 2));
}
static int nPeaks(int[] array, int range) {
// Check for special cases
if (array == null) {
return 0;
}
int result = 0, l, r;
// Check main body
for (int i = 0; i < array.length; i++) {
boolean isPeak = true;
// Check from left to right
l = Math.max(0, i - range);
r = Math.min(array.length - 1, i + range);
for (int j = l; j <= r; j++) {
// Skip if we are on current
if (i == j) {
continue;
}
if (array[i] < array[j]) {
isPeak = false;
break;
}
}
if (isPeak) {
System.out.println("Peak at " + i + " = " + array[i]);
result++;
i += range;
}
}
return result;
}
}
The last if condition shall throw exception when i == arr.length - 2.
This is because arr[i+2] in that case is out of bounds.
If you read the ArrayIndexOutOfBoundsException stack trace, it will tell you a line of code the error happened on. Look on that line of code and you'll probably see arr[i+1] or arr[i-1] or something. Certainly, at least one access on that line will be out of bounds. That's the problem.

Using Binary Search with sorted Array with duplicates [duplicate]

This question already has answers here:
Finding multiple entries with binary search
(15 answers)
Closed 3 years ago.
I've been tasked with creating a method that will print all the indices where value x is found in a sorted array.
I understand that if we just scanned through the array from 0 to N (length of array) it would have a running time of O(n) worst case. Since the array that will be passed into the method will be sorted, I'm assuming that I can take advantage of using a Binary Search since this will be O(log n). However, this only works if the array has unique values. Since the Binary Search will finish after the first "find" of a particular value. I was thinking of doing a Binary Search for finding x in the sorted array, and then checking all values before and after this index, but then if the array contained all x values, it doesn't seem like it would be that much better.
I guess what I'm asking is, is there a better way to find all the indices for a particular value in a sorted array that is better than O(n)?
public void PrintIndicesForValue42(int[] sortedArrayOfInts)
{
// search through the sortedArrayOfInts
// print all indices where we find the number 42.
}
Ex: sortedArray = { 1, 13, 42, 42, 42, 77, 78 } would print: "42 was found at Indices: 2, 3, 4"
You will get the result in O(lg n)
public static void PrintIndicesForValue(int[] numbers, int target) {
if (numbers == null)
return;
int low = 0, high = numbers.length - 1;
// get the start index of target number
int startIndex = -1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] > target) {
high = mid - 1;
} else if (numbers[mid] == target) {
startIndex = mid;
high = mid - 1;
} else
low = mid + 1;
}
// get the end index of target number
int endIndex = -1;
low = 0;
high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] > target) {
high = mid - 1;
} else if (numbers[mid] == target) {
endIndex = mid;
low = mid + 1;
} else
low = mid + 1;
}
if (startIndex != -1 && endIndex != -1){
for(int i=0; i+startIndex<=endIndex;i++){
if(i>0)
System.out.print(',');
System.out.print(i+startIndex);
}
}
}
Well, if you actually do have a sorted array, you can do a binary search until you find one of the indexes you're looking for, and from there, the rest should be easy to find since they're all next to each-other.
once you've found your first one, than you go find all the instances before it, and then all the instances after it.
Using that method you should get roughly O(lg(n)+k) where k is the number of occurrences of the value that you're searching for.
EDIT:
And, No, you will never be able to access all k values in anything less than O(k) time.
Second edit: so that I can feel as though I'm actually contributing something useful:
Instead of just searching for the first and last occurrences of X than you can do a binary search for the first occurence and a binary search for the last occurrence. which will result in O(lg(n)) total. once you've done that, you'll know that all the between indexes also contain X(assuming that it's sorted)
You can do this by searching checking if the value is equal to x , AND checking if the value to the left(or right depending on whether you're looking for the first occurrence or the last occurrence) is equal to x.
public void PrintIndicesForValue42(int[] sortedArrayOfInts) {
int index_occurrence_of_42 = left = right = binarySearch(sortedArrayOfInts, 42);
while (left - 1 >= 0) {
if (sortedArrayOfInts[left-1] == 42)
left--;
}
while (right + 1 < sortedArrayOfInts.length) {
if (sortedArrayOfInts[right+1] == 42)
right++;
}
System.out.println("Indices are from: " + left + " to " + right);
}
This would run in O(log(n) + #occurrences)
Read and understand the code. It's simple enough.
Below is the java code which returns the range for which the search-key is spread in the given sorted array:
public static int doBinarySearchRec(int[] array, int start, int end, int n) {
if (start > end) {
return -1;
}
int mid = start + (end - start) / 2;
if (n == array[mid]) {
return mid;
} else if (n < array[mid]) {
return doBinarySearchRec(array, start, mid - 1, n);
} else {
return doBinarySearchRec(array, mid + 1, end, n);
}
}
/**
* Given a sorted array with duplicates and a number, find the range in the
* form of (startIndex, endIndex) of that number. For example,
*
* find_range({0 2 3 3 3 10 10}, 3) should return (2,4). find_range({0 2 3 3
* 3 10 10}, 6) should return (-1,-1). The array and the number of
* duplicates can be large.
*
*/
public static int[] binarySearchArrayWithDup(int[] array, int n) {
if (null == array) {
return null;
}
int firstMatch = doBinarySearchRec(array, 0, array.length - 1, n);
int[] resultArray = { -1, -1 };
if (firstMatch == -1) {
return resultArray;
}
int leftMost = firstMatch;
int rightMost = firstMatch;
for (int result = doBinarySearchRec(array, 0, leftMost - 1, n); result != -1;) {
leftMost = result;
result = doBinarySearchRec(array, 0, leftMost - 1, n);
}
for (int result = doBinarySearchRec(array, rightMost + 1, array.length - 1, n); result != -1;) {
rightMost = result;
result = doBinarySearchRec(array, rightMost + 1, array.length - 1, n);
}
resultArray[0] = leftMost;
resultArray[1] = rightMost;
return resultArray;
}
Another result for log(n) binary search for leftmost target and rightmost target. This is in C++, but I think it is quite readable.
The idea is that we always end up when left = right + 1. So, to find leftmost target, if we can move right to rightmost number which is less than target, left will be at the leftmost target.
For leftmost target:
int binary_search(vector<int>& nums, int target){
int n = nums.size();
int left = 0, right = n - 1;
// carry right to the greatest number which is less than target.
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
// when we are here, right is at the index of greatest number
// which is less than target and since left is at the next,
// it is at the first target's index
return left;
}
For the rightmost target, the idea is very similar:
int binary_search(vector<int>& nums, int target){
while(left <= right){
int mid = (left + right) / 2;
// carry left to the smallest number which is greater than target.
if(nums[mid] <= target)
left = mid + 1;
else
right = mid - 1;
}
// when we are here, left is at the index of smallest number
// which is greater than target and since right is at the next,
// it is at the first target's index
return right;
}
I came up with the solution using binary search, only thing is to do the binary search on both the sides if the match is found.
public static void main(String[] args) {
int a[] ={1,2,2,5,5,6,8,9,10};
System.out.println(2+" IS AVAILABLE AT = "+findDuplicateOfN(a, 0, a.length-1, 2));
System.out.println(5+" IS AVAILABLE AT = "+findDuplicateOfN(a, 0, a.length-1, 5));
int a1[] ={2,2,2,2,2,2,2,2,2};
System.out.println(2+" IS AVAILABLE AT = "+findDuplicateOfN(a1, 0, a1.length-1, 2));
int a2[] ={1,2,3,4,5,6,7,8,9};
System.out.println(10+" IS AVAILABLE AT = "+findDuplicateOfN(a2, 0, a2.length-1, 10));
}
public static String findDuplicateOfN(int[] a, int l, int h, int x){
if(l>h){
return "";
}
int m = (h-l)/2+l;
if(a[m] == x){
String matchedIndexs = ""+m;
matchedIndexs = matchedIndexs+findDuplicateOfN(a, l, m-1, x);
matchedIndexs = matchedIndexs+findDuplicateOfN(a, m+1, h, x);
return matchedIndexs;
}else if(a[m]>x){
return findDuplicateOfN(a, l, m-1, x);
}else{
return findDuplicateOfN(a, m+1, h, x);
}
}
2 IS AVAILABLE AT = 12
5 IS AVAILABLE AT = 43
2 IS AVAILABLE AT = 410236578
10 IS AVAILABLE AT =
I think this is still providing the results in O(logn) complexity.
A Hashmap might work, if you're not required to use a binary search.
Create a HashMap where the Key is the value itself, and then value is an array of indices where that value is in the array. Loop through your array, updating each array in the HashMap for each value.
Lookup time for the indices for each value will be ~ O(1), and creating the map itself will be ~ O(n).
Find_Key(int arr[], int size, int key){
int begin = 0;
int end = size - 1;
int mid = end / 2;
int res = INT_MIN;
while (begin != mid)
{
if (arr[mid] < key)
begin = mid;
else
{
end = mid;
if(arr[mid] == key)
res = mid;
}
mid = (end + begin )/2;
}
return res;
}
Assuming the array of ints is in ascending sorted order; Returns the index of the first index of key occurrence or INT_MIN. Runs in O(lg n).
It is using Modified Binary Search. It will be O(LogN). Space complexity will be O(1).
We are calling BinarySearchModified two times. One for finding start index of element and another for finding end index of element.
private static int BinarySearchModified(int[] input, double toSearch)
{
int start = 0;
int end = input.Length - 1;
while (start <= end)
{
int mid = start + (end - start)/2;
if (toSearch < input[mid]) end = mid - 1;
else start = mid + 1;
}
return start;
}
public static Result GetRange(int[] input, int toSearch)
{
if (input == null) return new Result(-1, -1);
int low = BinarySearchModified(input, toSearch - 0.5);
if ((low >= input.Length) || (input[low] != toSearch)) return new Result(-1, -1);
int high = BinarySearchModified(input, toSearch + 0.5);
return new Result(low, high - 1);
}
public struct Result
{
public int LowIndex;
public int HighIndex;
public Result(int low, int high)
{
LowIndex = low;
HighIndex = high;
}
}
public void printCopies(int[] array)
{
HashMap<Integer, Integer> memberMap = new HashMap<Integer, Integer>();
for(int i = 0; i < array.size; i++)
if(!memberMap.contains(array[i]))
memberMap.put(array[i], 1);
else
{
int temp = memberMap.get(array[i]); //get the number of occurances
memberMap.put(array[i], ++temp); //increment his occurance
}
//check keys which occured more than once
//dump them in a ArrayList
//return this ArrayList
}
Alternatevely, instead of counting the number of occurances, you can put their indices in a arraylist and put that in the map instead of the count.
HashMap<Integer, ArrayList<Integer>>
//the integer is the value, the arraylist a list of their indices
public void printCopies(int[] array)
{
HashMap<Integer, ArrayList<Integer>> memberMap = new HashMap<Integer, ArrayList<Integer>>();
for(int i = 0; i < array.size; i++)
if(!memberMap.contains(array[i]))
{
ArrayList temp = new ArrayList();
temp.add(i);
memberMap.put(array[i], temp);
}
else
{
ArrayList temp = memberMap.get(array[i]); //get the lsit of indices
temp.add(i);
memberMap.put(array[i], temp); //update the index list
}
//check keys which return lists with length > 1
//handle the result any way you want
}
heh, i guess this will have to be posted.
int predefinedDuplicate = //value here;
int index = Arrays.binarySearch(array, predefinedDuplicate);
int leftIndex, rightIndex;
//search left
for(leftIndex = index; array[leftIndex] == array[index]; leftIndex--); //let it run thru it
//leftIndex is now the first different element to the left of this duplicate number string
for(rightIndex = index; array[rightIndex] == array[index]; rightIndex++); //let it run thru it
//right index contains the first different element to the right of the string
//you can arraycopy this [leftIndex+1, rightIndex-1] string or just print it
for(int i = leftIndex+1; i<rightIndex; i++)
System.out.println(array[i] + "\t");

Categories

Resources