recursive function not working for CheckLink function - java

I have below code but when i try to run the check function its giving me stackOverFlow error please help
when i debugged it its going till "return true;", but also entering else.
NOTE :
I have this data in my collection :
{1=[2, 3], 2=[3], 3=[4], 4=[3], 5=[6], 6=[5]}
How can i find the link between two nodes
private Map<Integer, ArrayList<Integer>> graphList = new HashMap<Integer, ArrayList<Integer>>();
private boolean checkLink(ArrayList<Integer> dataListFirst, int match) {
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (data == match) {
return true;
} else {
checkLink(graphList.get(data), match);
}
}
}
return false;
}

You are not using the retun value of your recursive call:
if (data == match) {
return true;
} else {
checkLink(graphList.get(data), match); // <--- Return value unused
}
You can modify your code to check if the recursive calls find your element:
private boolean checkLink(ArrayList<Integer> dataListFirst, int match) {
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (data == match || checkLink(graphList.get(data), match)) {
return true;
}
}
}
return false;
}
This code still could has a problem if your graph has cycles, you could return false in your function when you are trying to check the same value again.
// Just call the recursive function with an empty list of elements
private boolean checkLink(ArrayList<Integer> dataListFirst, int match) {
return checkLink(dataListFirst, match, new ArrayList<Integer>());
}
private boolean checkLink(ArrayList<Integer> dataListFirst, int match, List<Integer> nodes) {
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (nodes.contains(data)) {
return false;
}
nodes.add(data);
if (data == match || checkLink(graphList.get(data), match, nodes)) {
return true;
}
}
}
return false;
}

It seems to me you only want to make a recursive call after checking all the elements of the current ArrayList. And you should use the value returned by the recursive call (that's the reason your recursion didn't end after return true;) :
private boolean checkLink(ArrayList<Integer> dataListFirst, int match)
{
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (data == match) {
return true;
}
}
for (int data : dataListFirst) {
boolean found = checkLink(graphList.get(data), match);
if (found)
return found;
}
}
return false;
}
I'm not sure this will work in all cases, though, since if there are cycles in the graph you may get into an infinite recursion without ever finding the desired node.

Related

How to java Program to Check if an array contains a given two different values?

I want to write a code to check the existence of given two values in a List.
List<Tag> tags = new ArrayList<>();
The requirement is to return true only if the List tag contains both "start" and "end" values.
My code is like this, but it doesn't cater to the requirement.
public static boolean checkStartAndEndTimeTag(List<Tag> tags) {
boolean isSuccess = false;
int count = 0;
for (Tag tag : tags) {
if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
count++;
if (count == 2)
break;
isSuccess = true;
}
}
return isSuccess;
Can someone help me with to resolve this issue?
This...
if (count == 2)
break;
isSuccess = true;
doesn't make sense. This will set isSuccess even if there is only one match
The long winded approach
Okay, let's assuming for a second that you only care if there is at least one start and one end (discounting duplicates). One approach would be to use to state flags, one for start and one for end. To keep it simple, they would start of as 0 but would only ever be a maximum of 1 (because we don't want duplicates), then you might be able to do something like...
public static boolean checkStartAndEndTimeTag(List<Tag> tags) {
boolean isSuccess = false;
int starts = 0;
int ends = 0;
for (Tag tag : tags) {
if (tag.getKey().equals("start")) {
starts = 1;
} else if (tag.getKey().equals("end")) {
ends = 1;
}
}
isSuccess = (starts + ends) == 2;
return isSuccess;
}
Ok, you don't need isSuccess = (starts + ends) == 2; and could simply return the result of the comparison. You could also break out of the loop if (starts + ends) == 2 and save yourself from unnecessary computation
for (Tag tag : tags) {
if (tag.getKey().equals("start")) {
starts = 1;
} else if (tag.getKey().equals("end")) {
ends = 1;
}
if ((starts + ends) == 2) {
break;
}
}
Using streams...
One approach might be to make use the streams support and simply filter the List and count the results, for example...
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
List<Tag> tags = new ArrayList<Tag>(25);
tags.add(new Tag("begin"));
tags.add(new Tag("front"));
tags.add(new Tag("start"));
tags.add(new Tag("finish"));
tags.add(new Tag("tail"));
tags.add(new Tag("end"));
boolean isSuccessful = tags.stream().filter(tag -> tag.getKey().equals("start") || tag.getKey().equals("end")).count() >= 2;
System.out.println(isSuccessful);
}
public class Tag {
private String key;
public Tag(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
}
Updated...
Okay, this got complicated fast. Let's assume you don't want to match two start tags, so you MUST have both one end and one start tag
So, using the above, example, we can modify the Tag class to support equals (and by extension hashcode)
public class Tag {
private String key;
public Tag(String key) {
this.key = key;
}
public String getKey() {
return key;
}
#Override
public String toString() {
return getKey();
}
#Override
public int hashCode() {
int hash = 7;
hash = 73 * hash + Objects.hashCode(this.key);
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Tag other = (Tag) obj;
if (!Objects.equals(this.key, other.key)) {
return false;
}
return true;
}
}
Then we can simply use distinct to filter out any duplicates, for example...
boolean isSuccessful = tags
.stream()
.distinct()
.filter(tag -> tag.getKey().equals("start") || tag.getKey().equals("end"))
.count() >= 2;
Probably not the most efficient solution, but certainly one of the shortest
In this code
if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
count++;
if (count == 2)
break;
isSuccess = true;
}
you are setting isSuccess to true whenever the tag is start or end.
Better way would be
if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
count++;
if (count == 2)
return true;
}
You could also use
tags.stream()
.map(Tag::getKey)
.distinct()
.filter(t -> "start".equals(t) || "end".equals(t))
.count() == 2;
This would also fix the issue that your original code falsely returns true if the list contains statt or end twice.
What about
tags.containsAll(Arrays.asList(new Tag("start"), new Tag("stop")))

How to check if a Binary Search Tree is Perfectly Balanced?

I have this homework problem and I have completed all methods except this one, isPerfectlyBalanced().
All my tests pass except one that should return false but instead returns true. I have attached my current code and the test that is failing. Any description on how to go about this or even let me know where my code is wrong is appreciated!
private boolean isPerfectlyBalanced(Node node) {
if (node == null) {
return true;
}
if(size(node.left) == size(node.right)) {
return true;
}
isPerfectlyBalanced(node.left);
isPerfectlyBalanced(node.right);
return false;
}
public boolean isPerfectlyBalancedS() {
// TODO
if (root == null) {
return true;
}
return isPerfectlyBalanced(root);
}
Here is my test that is failing:
assertFalse(set.isPerfectlyBalancedS());
Thank you!
My size method:
private int size(Node node){
if (node == null){
return 0;
} else {
return (size(node.left) + 1 + size(node.right));
}
}
public int size() {
// TODO
return size(root);
}
On the last line of the first method, you probably want to do this:
return (isPerfectlyBalanced(node.left) && isPerfectlyBalanced(node.right));
instead of
isPerfectlyBalanced(node.left);
isPerfectlyBalanced(node.right);
return false;
In your code, you dismiss the result of the isPerfectlyBalanced on the subtrees and always return false.

Check whether there are remaining items in the List while iterating

I'm doing a Bean Validation for a List of conditions:
public abstract class BaseMyConditionValidator<T extends Annotation> implements ConstraintValidator<T, List<MyCondition>> {
#Override
public void initialize(T constraintAnnotation) {}
#Override
public boolean isValid(List<MyCondition> conditions, ConstraintValidatorContext context) {
boolean result = true;
if (!conditions.isEmpty()){
int i = 0;
for (MyCondition cond : conditions){
if (cond.getJoinPart() != null){
if (!hasNext(i, conditions)){
return false;
}
}
i++;
}
}
return result;
}
private boolean hasNext(int index, List<MyCondition> conditions){
try {
conditions.get(index + 1);
} catch (Exception e){
return false;
}
return true;
}
}
My question is is there a simpler approach to deal with:
Checking if there is still an item next in line during a iteration of a List
You could use plain old Iterator to iterate through the list, or instead of hasNext(i, conditions) just check list length (i < conditions.size() - 1)
In the end, instead of iterating through whole list, just check if last element's JoinPart is null (at least it is what you are doing)
#Override
public boolean isValid(List<MyCondition> conditions, ConstraintValidatorContext context) {
return conditions.isEmpty() || conditions.get(conditions.size() - 1).getJoinPart() != null;
}
In fact, in your case/code you don't need to check whether there is another element in the list. Using for(MyCondition cond : conditions) will iterate over all elements in conditions list. If you need to check what is the size of the list, you can use contidions.size().
Of course!
for (int i = 0; i < conditions.size(); i++){
cond = conditions.get(i);
if (cond.getJoinPart() != null){
if (i < conditions.size()){
continue;
} else {
return false;
}
}
}
But I don't understand why you would do that... are you just trying to ensure that .getJoinPart() doesn't equal null for every element?

Detecting multiple values in a list

I am having trouble with this problem: I am to write a method contains3 that accepts a List of strings as a parameter and returns true if any single string occurs at least 3 times in the list, and false otherwise. I need to use a map.
When there are three instances of a word, it still does not return true; I am having trouble locating where things went wrong.
Here is what I have:
private static boolean contains3(List<String> thing) {
Map<String, Integer> wordCount = new TreeMap<String, Integer>();
for (String s: thing) {
String word = s;
if (wordCount.containsKey(word)) { // seen before.
int count = wordCount.get(word);
wordCount.put(word, count + 1);
} else {
wordCount.put(word, 1); // never seen before.
}
if (wordCount.containsValue(3)) {
return true;
} else {
return false;
}
}
return false;
}
The problem is here:
if (wordCount.containsValue(3)) {
//...
You should get the value using the key, in other words, the word you're counting.
if (wordCount.get(word) >= 3) {
return true;
}
Note that I removed the return false; from this if statement since it will break the method in the first iteration.
As a suggestion, you may use a HashMap instead of TreeMap to enhance the performance of your method since the put and get time in HashMap are O(1) (constant time) while TreeMap's are O(log n).
Try using the following code.
private static boolean contains3(List<String> thing) {
Map<String, Integer> wordCount = new TreeMap<String, Integer>();
thing.add("hi");
thing.add("hi");
thing.add("hi");
thing.add("hia");
thing.add("hi3");
for (String s: thing) {
String word = s;
if (wordCount.containsKey(word)) { // seen before.
int count = wordCount.get(word);
wordCount.put(word, count + 1);
} else {
wordCount.put(word, 1); // never seen before.
}
}
if (wordCount.containsValue(3)) {
return true;
} else {
return false;}
You're running this code as you add each word:
if (wordCount.containsValue(3)) {
return true;
} else {
return false;
The test will fail when the first word is added, and you'll immediately return false. Move that block to the end of the method, in the final line where you currently have return false to only make the check when you've counted all the words.
put
if (wordCount.containsValue(3)) {
return true;
} else {
return false;
}
outside the for loop
It is much more efficient to check if count is >= 3 in the initial if block
if (wordCount.containsKey(word)) { // seen before.
int count = wordCount.get(word) + 1;
if(count >= 3) {
return true;
}
wordCount.put(word, count);
}
and remove the following if else block
if (wordCount.containsValue(3)) {
return true;
} else {
return false;
}

Using Recursive method in java

for homework I was asked to write a contain method for a custom linked list.
I know that the recursive method should have a base case and then the recursive case.However, I am having some trouble understanding how to write the recursive case of the method. So far this is what I have written, but my code is executing the base case more than once. Can you please give me some guidance?
public class OrderedList {
private Node first;
//Constructor
public OrderedList() {
this.first = null;
}
//Return the number of items in the list
public int size() {
int counter = 0;
Node pointer = this.first;
while (pointer != null) {
counter++;
pointer = pointer.next;
}
return counter;
}
//Return an array of copies of the stored elements
public Comparable[] getStore() {
Comparable[] elements = new Comparable[size()];
Node pointer = this.first;
if (this.first == null) {
return elements;
} else {
int i = 0;
while (pointer != null) {
elements[i] = pointer.data;
pointer = pointer.next;
i++;
}
return elements;
}
}
//true iff item matches a stored element
//Recursive
public boolean contains(Comparable item) {
//Base case
if (this.first == null) {
return false;
}
Node pointer = this.first;
this.first = this.first.next;
if (pointer.data.compareTo(item) == 0) {
return true;
}
//Recursive case
else {
boolean info = contains(item);
pointer.next = this.first;
this.first = pointer;
return info;
}
}
First of all I like to do something like this:
public boolean contains(Comparable item)
{
return containsHelper(this.first, Comparable item);
}
private boolean containsHelper(Node node, Comparable item)
{
//base case
if(node == null)
{
return false;
}
else
{
if(node.data.compareTo(item) == 0)
{
return true;
}
return containsHelper(node.next, item);
}
}
This hides implementation details from the user and it stops your list from getting overridden when you run that method.
To implement a recursive solution, you need an auxiliary method for contains. The auxiliary method should have an additional argument that is the Node from which to start testing. The public contains method should call the auxiliary method and pass this.first as the start node. The rest of the logic should then be pretty simple for you to figure out.
From what I am seeing, your code will return true once the else statemnet have been executed once. I think what you need to do is to set the boolean value to false everytime because recursion acts very much like a while loop and if the values are not updated, the base case would be executed over and over again.

Categories