Searching LinkedHashMap Using nested for loops - java

I have a LinkedHashMap like so
LinkedHashMap <Integer, ArrayList<Integer>> indexToIndecies = new LinkedHashMap <Integer ,ArrayList<Integer>>();
I have a method public int searchGraph(int baseIndex, int searchIndex, int count)
the point of this search method is; when some one enters baseIndex, which is a key, it has to find how many "clicks" it takes to get to the searchIndex. the values of the keys are the indexes to which they relate. So a "click" would be going from one key to another. So if my hashmap looks like:
0[2]
1[0, 3]
2[0, 5]
3[0, 2, 4, 5]
4[5]
5[2]
6[3, 4, 5]
7[1, 4]
to get from 0 to 5 takes two clicks.
so this is the code I have for my method:
public int searchGraph(int baseIndex, int searchIndex, int count)
{
if (baseIndex == searchIndex)
{
return count;
}
if (searchIndex > indexToIndecies.size()-1){
return -3;
}
else{
for (int i = 0; i < indexToIndecies.get(baseIndex).size(); i++)
{
for (int x = 0; x< indexToIndecies.get(baseIndex).size(); x++){
if (indexToIndecies.get(baseIndex).get(x) == searchIndex){
return count;
}
else{
count++;
}
}
baseIndex = (indexToIndecies.get(baseIndex)).get(i);
}
return count;
}
}
Works fine If The baseIndex and seachIndex I give it has an association, however if it doesn't I am not sure how to catch that... Any help will be appreciated.

Right now you're not accounting for the possibility that there may be multiple paths from the baseIndex to the searchIndex - presumably you want the shortest path if this is the case. One way to correct for this is to replace the nested for loops with a single for loop around a recursive call. Return Integer.MAX_VALUE if a path isn't found, then if your shortest path has a count of Integer.MAX_VALUE then you'll know that you weren't able to find a path. (If you DID find a path with a count of Integer.MAX_VALUE then something probably went wrong with your path-finding algorithm - you shouldn't have paths that are that long.) If you want to use nested loops instead of recursion then you can convert the recursive call into a loop by using your own stack variable.
public int searchGraph(int baseIndex, int searchIndex, int count) {
if(baseIndex == searchIndex) {
return count;
} else if(count > indexToIndecies.size()) {
return Integer.MAX_VALUE; // cycle in graph
} else {
int returnVal = Integer.MAX_VALUE;
for(int i = 0; i < indexToIndecies.get(baseIndex).size(); i++) {
int temp = searchGraph(indexToIndecies.get(baseIndex).get(i), searchIndex, count + 1);
returnVal = temp < returnVal ? temp : returnVal;
}
return returnVal;
}
}
This should return the shortest path, and if it returns Integer.MAX_VALUE then a path wasn't found.
Another option is to return an Integer instead of an int, in which case you can return a null in the case that you couldn't find a path.
Edit: SimonC pointed out in the comments that a cycle in the graph could cause a stack overflow. I've corrected for this by returning Integer.MAX_VALUE if count exceeds indexToIndecies.size(), since count shouldn't exceed the number of keys in the map.

Related

How to recursively count number of occurences in an array

I've got a task that gets an int value "n" and an Int Array as parameters and is supposed to return a boolean.
The method is supposed to determine, how many "n" are in the given Array. If the number is even the method should return true, else false. If the Array has the length 0, it should return "false" aswell.
What i managed to do is :
public static boolean evenNumberOf(int n, int[] arr) {
boolean result = false;
System.out.println("Starting count");
if (n < arr.length) {
if (arr[n] == n) {
result = true;
} else {
return evenNumberOf(n - 1, arr);
}
}
return result;
}
Im just really confused and i dont know what to do to be honest. I have really tried my best but the longer i work on this task the less i understand.
Any help is appreciated and thank you in advance! :)
Separate it into two methods:
The method you call initially
and a method that gets called recursively to count the number of ns in the array:
boolean evenNumberOf(int n, int[] arr) {
int count = countNs(n, arr, 0);
// Logic to choose what to return based on count and/or length of arr.
}
int countNs(int n, int[] arr, int i) {
// Check if arr[i] is equal to n.
// Make a recursive call to countNs for i := i + 1.
// Combine the check/recursive call result to return a value.
}
Try
//arr should not be empty, index and count >= 0
public static boolean evenNumberOf(int value, int index,int[]arr, int count) {
if(index >= arr.length) return count%2 == 0;
if(arr[index] == value ) {
count++;
}
return evenNumberOf(value, ++index, arr, count);
}
Usage example: System.out.println(evenNumberOf(2, 0, new int[]{2,0,3,7,6,11,1,2}, 0));
(You can add an helper method evenNumberOf(int value,int[]arr))
as Recursive Counting in an Array got closed as a duplicate I will answer it here:
Let's analyze what you did and why it's wrong
public static int countN(int n,int [] arr,int i, int count) {
if (arr[i] == n) {
System.out.println("MATCH");
count++;
return count;
}
Here you already return the count when you get a match. You shouldn't do that because if the first number is already the same it returns 1. all you need to do is increase the count here
else {
System.out.println("Moving on");
i = i + 1;
countN(n,arr,i, count);
}
Here you do the recursion. This is good. But this also needs to be done in the case that you do get a match. And it needs to return that value. But, also this only needs to be done when you are not at the end of the array yet
if (arr.length == i) {
evenNumberOf(n,arr);
}
this part doesn't make sense, because you call evenNumberOf with the exact same arguments as it started so it will result in an infinite loop. you should have returned the count here. also keep in mind that the last index of an array is length - 1
putting this together you can make:
public static int countN(int n,int [] arr,int i, int count) {
if (arr[i] == n) {
count++;
}
if (arr.length - 1 == i) {
return count;
}
return countN(n, arr, i + 1, count);
}

Why is my recursive binary search only finding some matches not all of them? (Java)

I'm trying to search through an array of DrillingRecord objects where each object contains an array within itself. I have to find a value at a specific index in the internal array for each object, and then output the array as well as keep track of matches. The search is partially working as it will find some values but not all of them.
//record is empty. I put it there so I wouldn't have to call it every time.
public String binarySearch( int index, int first, int last, double key, int amount, DrillingRecord record) {
if (last >= first) {
int mid = first + (last - first) / 2;
if (mid < count) { //count is size of the array of objects, data[]
for (int j = 0; j <= mid; j++) {
record = (DrillingRecord) data[j]; //Object[] array hence the cast
double[] dataRecord = record.getNums(); //getNums returns array of doubles
if (dataRecord[index-2] == key) { //index-2 is not the problem
amount++;
System.out.println(record.noErrors()); // noErrors is basically toString
}
}
record = (DrillingRecord) data[mid];
double[] dataRecord = record.getNums();
if (dataRecord[index-2] < key ) {
return binarySearch(index, first, mid+1, key, amount, record);
} else if (dataRecord[index-2] > key) {
return binarySearch(index, mid-1, last, key, amount, record);
}
}
}
if (amount == 0) {
return "-1 /n Drilling records found: " + amount;
}
return "Drilling records found: " + amount;
}
For example, I know there are 4 records with a value of 12.0 at index 3, but when I run the program it says it only found 2. I've been troubleshooting this for a while, and I suspect it has something to do with the for loop I'm just not quite sure what that is.
Thank you for any help it's much appreciated.

How to find the maximum value in a linked list recursively?

I need to find the maximum value in a linked list given the head of the list as a parameter recursively. I have no clue how to start the recursive part of the method. This is all I have so far.
int maxOfList(List M){
List max = M;
if(M == null)
return max;
if(M.next > max){
max = M.restOfTheInts;
return maxOfList();
}
}
In recursion, you often need an entry method and a worker method. The entry method is the special case that allows the worker method to work in all cases, and the worker does the recursion.
For example, your worker might be something like:
int maxOfList(int currentMax, List<int> listToCheck) {
// Nothing to compare? currentMax is it!
if (listToCheck == null || listToCheck.size() == 0) return currentMax;
// Compare and return.
List<int> restOfList = listToCheck.subList(1, listToCheck.size());
return maxOfList(Math.max(currentMax, listToCheck.get(0)), restOfList);
}
And then to kick that off, you need your entry method:
int maxOfList(List<int> listToCheck) {
return maxOfList(Integer.MIN_VALUE, listToCheck);
}
So, for recursion to effectively work, you need to have the whole context visible inside the function.
int maxOfList(List m) {
if(m.next == null)
return m;
int previousMax = maxOfList(m.next);
if(m > previousMax)
return m;
else
return previousMax;
}
int maxValue(List m){
return maxValue(m, Integer.MIN_VALUE);
}
int maxValue(List m, int num){
if(m.next == null){
if(m.data > num)
return num = m.data;
}
return maxValue(m.next, num);
}
This should be pretty straightforward. In order to achieve a recursive solution, think about all these steps:
What's the recursive idea? The maximum of a list {L} is the max(Li, {L} - Li), where Li is the current element;
What's the stop condition? We know that if a list is empty, the maximum could be something that any number will be greater, let's say MIN_INT;
Putting all together: So, at the end we could say that a pseudo-code would look like this:
int maxOfList(List M) {
if(M == null)
return Integer.MIN_VALUE;
int max = maxOfList(M.next);
return M.value > max ? M.value : max;
}
I am supposing that the linked list has its content in value and points to next element in next (tail pointing to null). If you find any further problems, take a look at this posts:
Finding Max value in an array using recursion
Python: Recursive function to find the largest number in the list

How to find the location of the largest element in an array using recursion?

Given an array list, and the count of element on the list find the location of the largest element using recursion.
So far, I'm able to find the largest element, but I need the location of that element on the array and not the actual value.
private int getLargestElementLoca(int[] list, int count)
{
int largestValue;
if(count == 1){
return 0;
}
int tempMax = getLargestElementLoca(list,count-1);
largestValue = Math.max(list[count-1],tempMax);
return largestValue;
}
You're on the right track, but you just need some tweaks. I'm not going to write the code for you, but here are some clues.
If you want your function to return the index instead of the maximum value, then you need to change the way you compute the return value and the way you use it recursively.
private int getLargestElementLoca(int[] list, int count)
{
int largestValue;
if(count == 1){
return 0;
}
If there is only one element to look at, i.e. list[0], then list[0] will be the maximum, and 0 will be its index. So returning 0 is correct here.
int tempMax = getLargestElementLoca(list,count-1);
You've redefined getLargestElementLoca so that it returns an index, not a maximum value. That applies to your recursive call also, so tempMax is going to be an index and not a value. That means that you can't pass it directly into Math.max. Some adjustment will be necessary, but keep reading.
largestValue = Math.max(list[count-1],tempMax);
Math.max returns the largest value, but that isn't what you want. You have two indexes, count-1 and something else, and you want to compute the index of the larger value. You can't do that with Math.max, but you can use an if statement or the conditional operator a ? b : c. It would also be helpful to rename the variable, since it's no longer going to contain the largest value.
An idea could be to split your array recursiv into two parts until there are only 2 or 1 elements remainning. Finding the max value in two numbers or one is simple und return it. Then you compare the two returned values and return the max.
Recursion is simple, but you should know about doing it iteratively:
private int getMaxLocation(int[] array) {
int maxpos = 0;
int max = Integer.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
maxpos = i;
}
}
return maxpos;
}
If you were to do this through recursion, you would need to track a few variables across it:
private int getMaxLocation(int[] array, int pos, int max, int maxpos) {
if (pos >= array.length || pos < 0) {
return maxpos;
} else {
int current = array[pos];
if (current > max) {
max = current;
maxpos = pos;
}
return getMaxLocation(array, ++pos, max, maxpos);
}
}
//calling this
int max = getMaxLocation(yourArray, 0, Integer.MIN_VALUE, 0);

Why doesn't this return the position for the largest item in the array list

public static int findLargestMark(ArrayList<Result> array)
{
int last = 0;
int largestPOS = 0;
for (int i = 1; i <= array.size(); i++)
{
for (Result s : array)
{
int num = s.getMark();
if (num > last)
{
last = num;
largestPOS = i++;
}
}
}
Does anyone have any idea why this isn't returning the position of the largest value?
I'm sorry but I'm a bit of a newbie to Java.
largestPOS = i++;
This is incrementing i which means it skips the next number. If that next number is the biggest, you'll miss it.
Your code won't compile. You need a return statement.
Your outer loop skips the first element because it starts at 1 instead of 0. Arrays and lists are 0 based.
You only need one loop to accomplish this. I'd remove the inner loop since you're trying to return the index and a foreach loop doesn't give you the index.
If your array is empty, it will set largestPOS to 0. That is not correct. Other algorithms in this situation would return -1 to mean "index not found". See String.indexOf for example.
If you want to find the largest mark, no need to reinvent the wheel. Use Collections.max and provide a custom Comparator :
Result r = Collections.max(array, new Comparator<Result>() {
#Override
public int compare(Result o1, Result o2) {
return Integer.compare(o1.getMark(), o2.getMark());
}
});
Then if you really want to find the position of this object in the list you can use indexOf :
array.indexOf(r);
Note that will return the index of the first occurrence of the specified element in the list.
If you want to get the index of the last occurrence, you can use :
array.lastIndexOf(r);
There are several reasons to this program's failure:
You need to check that your array has at least one item
You need to start the last at the initial mark, not at zero
You need to loop from one, inclusive, to array.size(), exclusive
You do not need a nested loop
You need to add a return statement
Here is how you can fix your code:
public static int findLargestMark(ArrayList<Result> array) {
if (array.size() == 0) return -1; //
int last = array.get(0).getMark();
int largestPOS = 0;
for (int i = 1; i < array.size(); i++) {
int num = array.get(i).getMark();
if (num > last) {
last = num;
largestPOS = i;
}
}
return largestPOS;
}
Because you're iterating through the same array using two nested loops. Keep it simple. Iterate only once through the entire array and find the maximum value and its index.
Try this..
public static int findLargestMark(ArrayList<Result> array)
{
int last = array.get(0).getMark();
int largestPOS = 0;
for (int i = 1; i <= array.size(); i++)
{
Result s = array.get(i);
int num = s.getMark();
if (num > last)
{
last = num;
largestPOS = i;
}
}
return largestPOS;
}
Your code even not compile, java is 0 index based. you should have received a ArrayIndexOfBoundException. However, i would just use Collections.max(array, Comparator):
Result x = Collections.max(array, new Comparator<Result>(){
#Override
public int compare(Result o1, Result o2) {
return Integer.compare(o1.getMark(), o2.getMark());
}
});
And then the index by array.indexOf(x) function, where array is an instance of type ArrayList<Result>

Categories