boolean recursion - java

trying to write a boolean method that tells if someone is a decendant of someone...but can't seem to do it. of course, the object is a descendant if it's a child...or the descendant of a child.
public boolean isDescendant(member x){
if (children.contains(x)){
return true;
}
else{
return false;
}
}
but where or how do i insert:
for (int i = 0; i < children.size(); i++){
isDescendant(children.get(i));
}
thanks!

I think what you want is below:
// Cleaned up version
public boolean isDescendant(member x){
// check for direct descendance
if (children.contains(x)){
return true;
}
// check for being descendant of the children
for (Child c: children){
if (children.get(i).isDescendant(x)) {
return true;
}
}
return false;
}

Walking trees is very slow downwards (from the root to the leaves). Consider this implementation for the is-ancestor check:
/**
* Checks whether the given node is an ancestor of this node.
*/
public boolean isDescendantOf(Node ancestor) {
Preconditions.checkNotNull(ancestor, "Ancestor");
if (equals(ancestor)) {
// every node is an ancestor to itself
return true;
} else if (parent == null) {
// not related
return false;
} else {
// recursive call
return parent.isDescendantOf(ancestor);
}
}
The other way is now a piece of cake.
public boolean isDescendant(Node descendant) {
return descendant.isDescendantOf(this);
}
No loops, no exponentional effort.
PS:
In my example i would suggest renaming isDescendant to isAncestorOf.

public boolean isDescendant(member currentRoot, member x){
//check the current level
if (currentRoot.children().contains(x)){
return true;
}
//leaf
if( currentRoot.children().isEmpty() ){ return false; }
//try all my children
boolean found = false;
for( Member child : currentRoot.children() ){
found = isDescendant( child, x );
if( found ) break;
}
return found;
}
You need to recurse over the current root, most likely.

Edit: If your data structure has parent pointers, use these instead of searching your descendants in the tree. If not, consider adding them. See the answer from whiskeysierra for a solution with parent pointers. Only if adding them is not possible, consider this answer.
The current answers all have two loops through children (one in children.contains(), one later).
This variant may be a bit more efficient (but it does not change the O-class), and is a bit shorter. (If children is a set with fast contains-check (like HashSet) and often the hierarchy is not so deep (so you don't need to recurse at all), the other answers are better.)
public boolean isDescendant(Member x) {
for(Member child : children) {
if(child.equals(x) || child.isDescendant(x))
return true;
}
return false;
}
If a node is considered a descendant of itself, you can write it like this:
public boolean isDescendant(Member x) {
if(equals(x))
return true;
for(Member child : children) {
if(child.isDescendant(x))
return true;
}
return false;
}

Related

How to write an in-order traversal to check if its a valid BST but with keeping the previous node as a parameter?

I'm trying to write a recursive code to check if a binary search tree is valid using an in-order traversal but without using an array. In other words, using only a previous value. I'm trying to keep the previous value as a parameter, but the code is failing. I've trie debugging but not sure why the code is not working.
class Solution {
public boolean isValidBST(TreeNode root) {
return isValidBSTPrev(root, null);
}
public boolean isValidBSTPrev(TreeNode root, TreeNode prev) {
if(root == null) {
return true;
} else if(isValidBSTPrev(root.left, root)
&& (prev!=null && root.val > prev.val)
&& isValidBSTPrev(root.right, root)) {
return true;
} else {
return false;
}
}
}

Binary Tree path() Implementation

I am working on a programming assignment that requires us to write a path(root, value) method that returns a LinkedList of Direction Enums (left, right) that leads to the target node (value). We are not allowed to create any new fields to make this happen, which is why I've created a pathHelper() method. One of the tests I'm failing is supposed to return: left, right as the path but it's returning left, right, left, right. I'm not sure why it's counting the steps twice. Any suggestions would be appreciated!
NOTE: This is a Binary Tree, not a BST. We are supposed to use an exhaustive DFS approach.
public static <T> LinkedList<BinaryNode.Direction> path(BinaryNode<T> root, T value) {
if (root == null) {
return null;
} else if (root.payload == value) {
return new LinkedList<>();
}
LinkedList<BinaryNode.Direction> list = new LinkedList<>();
pathHelper(root, value, list);
return list;
}
public static <T> void pathHelper(BinaryNode<T> root, T value, LinkedList<BinaryNode.Direction> list) {
if (root.left != null) {
if (root.payload != value) {
list.add(BinaryNode.Direction.left);
}
pathHelper(root.left, value, list);
} if (root.right != null) {
if (root.payload != value) {
list.add(BinaryNode.Direction.right);
}
pathHelper(root.right, value, list);
}
}
Your code has quite a few errors in it so I'm surprised any test cases are passing. You seem to be storing directions as you search the tree rather than when you find the value.
I suspect you are overcomplicating the problem. If you return a boolean from your helper function based on whether the item is found then you can easily add the directions when you return from the recursion:
private boolean findPath(BinaryNode<T> node, T value, List<BinaryNode.Direction> directions) {
if (node == null) {
return false;
} else if (node.payload.equals(value)) {
return true;
} else if (findPath(node.left, value, directions)) {
directions.add(0, BinaryNode.Direction.LEFT);
return true;
} else if (findPath(node.right, value, directions)) {
directions.add(0, BinaryNode.Direction.RIGHT);
return true;
} else {
return false;
}
}
Note that this inserts the direction at the start of the list to ensure it's in the correct order. This also allows you to detect where the root has the value because it will return true but the path will be empty.

finding loop in linked list using HashMap in java

i am writing code for lop detection in linked list using hashmap. why it goes in infinite loop?
boolean hasCycle(Node head) {
HashMap<Integer,Node> map = new HashMap<Integer,Node>();
//<Address,data>
if(head == null || head.next == null)
return false;
Node p = head;
while(p.next!=null)
{
if(map.containsValue(p.next))
{
return true;
}
else
{
map.put(p.data,p.next);
}
p = p.next;
}
return false;
}
Use the Node as key and the data field as value and then check whether the HashMap contains the key:
boolean hasCycle(Node head) {
HashMap<Node,Integer> map = new HashMap<Node,Integer>();
if(head == null || head.next == null)
return false;
Node p = head;
while(p.next!=null) {
if (map.containsKey(p.next)) {
return true;
} else {
map.put(p.next,p.data);
}
p = p.next;
}
return false;
}
And also follow the Java Code Conventions.
Your code calls
map.containsValue(p.next)
This method iterates through the whole map looking for an object that is equal to the passed argument. To do that, it calls your Node.equals() method. It is highly probable that this is where it's going into an infinite loop.
To solve it, you could just use a HashSet of the Node objects (as mentioned in the comments) and check that your equals() and hashCode() methods are correct. But there is also another way to check for cycles, which doesn't involve the use of any extra memory. You just use two iterators, one going at half the speed of the other. If there is a cycle, the faster iterator will lap the slower one.
Have you defined .equals() and .hashCode() on your Node class? if not, it defaults to ==, and if the HashMap makes a copy of your Node as it inserts or moves it in memory, and then your equivalence would fail, because == compares memory addresses.
assuming your node class is akin to
public class Node{
public int data;
public Node next;
}
you could define them as
#Override
public int hashCode(){
int nextData=next.data;
return data^nextData;
}
#Override
public boolean equals(Object other){
boolean equal=false;
if(other!=null&&other instanceof Node){
Node otherNode=(Node)other;
if(otherNode.data==data){
if(otherNode.next==null&&next==null){
equal=true;
}else if(otherNode.next!=null&&next!=null){
if(otherNode.next.data==next.data){
equal=true;
}
}
}
}
return equal;
}

Checking to see if a binary search tree is degenerate

I want to check if a binary search tree is degenerate or not (Is it a linked list or indeed a tree?) I've been trying for a while and have come up with nothing that works. I did come up with a nonrecursive solution which I thought was quite clever but the specifications state it has to be a recursive solution and I'm having translating it from non-recursive to recursive.
Here's my non-recursive solution (well not really because size and height are both implemented recursively. This method however is not).
public boolean isDegenerate(){
if(this.size() == this.getHeight()){
return true;
}
return false;
}
Well, if you want a "more recursive" solution, how about this?
public boolean isDegenerate() {
if (this.left != null) {
if (this.right != null) {
return false; // not degenerate, has two children
} else {
return this.left.isDegenerate();
}
} else {
if (this.right != null) {
return this.right.isDegenerate();
} else {
return true; // we arrived at the bottom without seeing any node with two children
}
}
}

How to change one Boolean based on values found in ArrayList?

I am trying to make a deductive Algorithm for solving a Sudoku puzzle. My Board is made up of 81 Nodes in an ArrayList.
- Each Node has a boolean Value
I want my algorithm (called CRME) to be continue to try and solve the puzzle if it finds that at least one of the nodes has it's boolean value (hasChanged) equal to true but I am unsure how to do this. canChange is also a global variable in the class this method is contained in.
public void CRME() {
canChange = true;
while (canChange == true) {
for (Node node : cells) {
scanColumn(node);
scanRow(node);
scanMiniGrid(node);
}
}
}
public void scanRow(Node n){
for(Node node : cells){
int arraySize = node.posVals.size();
ArrayList<Integer> toRemove = new ArrayList<Integer>();
if(node.get_ROW_ID() == n.get_ROW_ID()){
toRemove.add(node.getValue());
}
n.posVals.removeAll(toRemove);
if(arraySize < node.posVals.size()){
node.hasChanged = true;
}
}
}
This is the scanRow method, the two other similarly named methods are the same but with the obvious syntax changed, such as node.get_ROW_ID(); would be node.get_COL_ID();.
I assume you have a static variable
static boolean hasChanged; // in the Node class
so you can use:
node.hasChanged = true;
or you can create hasChange method to set the variable like so
boolean hasChanged;
public void hasChanged(boolean val){
this.hasChanged = val;
}
and use in the loop, like so:
hasChanged(true); or hasChanged(false);
Not saying your approach is best, but if you are trying to simply continue while one of hasChanged is true for any of your nodes, the following will suffice:
public void CRME()
{
goOn = false;
for (Node node : yourArrayListOfNodes)
{
if (node.hasChanged)
{
goOn = true;
break;
}
}
if (goOn)
{
//Insert Whatever code you want to run after the check
//.........................................
//Use recursion to repeat process
//Note recursive call will only take place if goOn is true
CRME()
}
}
This seems like what you want to do, just note that if your logic is incorrect, you can get a StackOverflowError, since you would keep making recursive calls.

Categories