I have to find and return the next larger node in the generic tree almost all testcases are running fine and giving correct output just one testcase is coming out wrong and it could be anything. I have debugged my program many times and could not figured out what bug that could be? Actually what I'm doing I'm comparing all the next larger nodes that recursion has fetched for me and comparing them with one another and ultimately find the right one? I'm stuck a little help would be appreciated.
Code
/* TreeNode structure
class TreeNode<T> {
T data;
ArrayList<TreeNode<T>> children;
TreeNode(T data){
this.data = data;
children = new ArrayList<TreeNode<T>>();
}
}*/
public static TreeNode<Integer> findNextLargerNode(TreeNode<Integer> root, int n){
if(root==null)
return root;
if(root.children.size()==0)
{
if(root.data>n)
{
return root;
}
else
return null;
}
TreeNode<Integer> count[] = new TreeNode[root.children.size()];
for(int i=0;i<root.children.size();i++)
{
count[i] = findNextLargerNode(root.children.get(i),n);
}
int nextLarger=Integer.MAX_VALUE;
TreeNode<Integer> next = null;
for(int i=0;i<count.length;i++)
{
if(count[i]!=null)
{
if(count[i].data>n && count[i].data<nextLarger)
{
nextLarger = count[i].data;
next = count[i];
}
}
}
if(next!=null)
{
if(root.data>n && root.data<next.data)
return root;
else
return next;
}
else
return null;
}
I see one extreme test which could fail: if the correct answer is a node that has as data Integer.MAX_VALUE, then your code will return null instead of that node.
A solution with the least change to your code, is to replace:
count[i].data<nextLarger
with:
count[i].data<=nextLarger
This way you are sure to give next a non-null value even if count[i].data is Integer.MAX_VALUE.
NB: If you would join both for loops into one, you would not need to use a count array, but just a single node variable.
Finally, I have found the bug in my code. It lies in the following segment.
if(next!=null)
{
if(root.data>n && root.data<next.data)
return root;
else
return next;
}
else
return null;
Suppose if next == null then else will get executed which will return the null. This is wrong because root can also be the next larger node so I have to check for that condition also
The correct version is :
if(next!=null)
{
if(root.data>n && root.data<next.data)
return root;
else
return next;
}
else
{
if(root.data>n)
return root;
else
return null;
}
Try
public class Test {
class TreeNode<T> {
T data;
List<TreeNode<T>> children;
TreeNode(T data) {
this.data = data;
children = new ArrayList<TreeNode<T>>();
}
public TreeNode<T> findNextNode(T n,Comparator<T> comp) {
if (comp.compare(data , n) < 0) {
return this;
}
if (children.size() == 0) {
return null;
}
for (int i = 0; i < children.size(); i++) {
TreeNode<T> node= children.get(i).findNextNode(n,comp);
if(node!=null)return node;
}
return null;
}
}
Explanation:
Tests
To show some errors in your code I provide a test in testForYourCode (see below). The test returns an unexpected result. The second child with a value of 4 wins which is wrong.
In TreeNode<T>.findNextNode I provide a 'refactored' version. Not sure if it does what you have asked for. The two tests testForModifiedCodeand testForModifiedCodeComplex show how the refactored version behaves.
Generic
Instead of writing a function that can deal only with TreeNode<Integer> I decided to write a generic function that works on all kind of types.
Comparison
The actual comparison is delegated to a Comparator object. An instance of a Comparator must be passed to the findNextNode method. This can be done on-the-fly using Java 8 lambda syntax, e.g. (a,b)->{return b-a;}. This adds some flexibility to the implementation. By changing the comparator you can also search for the 'next lesser node' using (a,b)->{return a-b;}.
What it does
If the entry node fulfills the criteria defined by the Comparator.compare implementation the algorithm stops. Otherwise a deep search is performed starting at the first child node (and so forth). As soon as the node matches the comparison criteria the algorithm stops. If no node matches, null is returned.
package stack43210199;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.junit.Assert;
public class Test {
class TreeNode<T> {
T data;
List<TreeNode<T>> children;
TreeNode(T data) {
this.data = data;
children = new ArrayList<TreeNode<T>>();
}
public TreeNode<T> findNextNode(T n,Comparator<T> comp) {
if (comp.compare(data , n) < 0) {
return this;
}
if (children.size() == 0) {
return null;
}
for (int i = 0; i < children.size(); i++) {
TreeNode<T> node= children.get(i).findNextNode(n,comp);
if(node!=null)return node;
}
return null;
}
}
#org.junit.Test
public void testForYourCode() {
TreeNode<Integer> root = buildNode(0);
TreeNode<Integer> firstChild = buildNode(5);
TreeNode<Integer> secondChild = buildNode(4);
TreeNode<Integer> thirdChild = buildNode(5);
root.children.add(firstChild);
root.children.add(secondChild);
root.children.add(thirdChild);
//Arrg - not as expected
Assert.assertEquals(secondChild, findNextLargerNode(root, 0));
}
#org.junit.Test
public void testForModifiedCode() {
TreeNode<Integer> root = buildNode(2);
TreeNode<Integer> firstChild = buildNode(5);
TreeNode<Integer> secondChild = buildNode(4);
TreeNode<Integer> thirdChild = buildNode(5);
TreeNode<Integer> fourthChild = buildNode(1);
root.children.add(firstChild);
root.children.add(secondChild);
root.children.add(thirdChild);
thirdChild.children.add(fourthChild);
//find next greater
Assert.assertEquals(firstChild, root.findNextNode(2,(a,b)->{return b-a;}));
//find next lesser
Assert.assertEquals(fourthChild, root.findNextNode(2,(a,b)->{return a-b;}));
}
#org.junit.Test
public void testForModifiedCodeComplex() {
TreeNode<Integer> root = buildNode(2);
TreeNode<Integer> firstChild = buildNode(2);
TreeNode<Integer> secondChild = buildNode(4);
TreeNode<Integer> thirdChild = buildNode(5);
TreeNode<Integer> fourthChild = buildNode(1);
TreeNode<Integer> sixthChild = buildNode(8);
firstChild.children.add(fourthChild);
firstChild.children.add(sixthChild);
root.children.add(firstChild);
root.children.add(secondChild);
root.children.add(thirdChild);
//find next greater
Assert.assertEquals(sixthChild, root.findNextNode(2,(a,b)->{return b-a;}));
//find next lesser
Assert.assertEquals(fourthChild, root.findNextNode(2,(a,b)->{return a-b;}));
}
private TreeNode<Integer> buildNode(int i) {
return new TreeNode<Integer>(new Integer(i));
}
public static TreeNode<Integer> findNextLargerNode(TreeNode<Integer> root, int n) {
if (root == null)
return root;
if (root.children.size() == 0) {
if (root.data > n) {
return root;
}
else
return null;
}
TreeNode<Integer> count[] = new TreeNode[root.children.size()];
for (int i = 0; i < root.children.size(); i++) {
count[i] = findNextLargerNode(root.children.get(i), n);
}
int nextLarger = Integer.MAX_VALUE;
TreeNode<Integer> next = null;
for (int i = 0; i < count.length; i++) {
if (count[i] != null) {
if (count[i].data > n && count[i].data < nextLarger) {
nextLarger = count[i].data;
next = count[i];
}
}
}
if (next != null) {
if (root.data > n && root.data < next.data)
return root;
else
return next;
} else {
if (root.data > n)
return root;
else
return null;
}
}
}
A TreeNode would normally look like this.
class TreeNode<T extends Comparable<T>> {
T data;
TreeNode<T> left, right;
TreeNode(T data){
this.data = data;
}
public TreeNode<T> findNextLargerNode(T t) {
if (data.compareTo(t) <= 0)
return right == null ? null : right.findNextLargerNode(t);
T found = left == null ? null : left.findNextLargerNode(t);
return found == null ? this : found;
}
}
Related
I am trying to insert in a binary search tree using recursion and then print it preorderly using this specific code, but I have only root as output,why?Is this because each time stack(after each call) is popping off thus removing new nodes?(This is a java code)
class node{
int data;
node left;
node right;
node(int key){
data = key;
left = right = null;
}
}
class bst{
node root;
node temp;
node last;
bst(){
root = null;
}
bst(int key){
root = new node(key);
}
void Insert(node r,int value){
temp = r;
if(temp == null){
if(root == null){
root = new node(value);
root.data = value;
return;
}
temp = new node(value);
temp.data = value;
return;
}
else{
if(value > temp.data){
Insert(temp.right,value);
return;
}
else{
Insert(temp.left,value);
return;
}
}
}
}
class test{
static void in_order(node root){
if(root == null){
return;
}
in_order(root.left);
System.out.println(root.data+" ");
in_order(root.right);
}
public static void main(String[] args){
bst tree = new bst();
tree.Insert(tree.root,45);
tree.Insert(tree.root,39);
tree.Insert(tree.root,12);
tree.Insert(tree.root,59);
test.in_order(tree.root);
}
}
The reason you are only getting a single integer for an output is because the first Insert call correctly adds the element to the tree, but subsequent calls fail because you overwrite the data member temp to null when you recursively insert to the left or right. Thus the second branch of your first if statement never gets executed.
You don't actually need the variable temp here. A common convention is to have a private, recursive member function that takes the root of the tree as a parameter returns the modified tree, and assign the return value to root in a public member function.
public void Insert(int value) {
root = Insert(root, value);
}
private node Insert(node r, int value) {
if (r == null) {
r = new node(value);
}
else if (value > r.data) {
r.right = Insert(r.right, value);
}
else {
r.left = Insert(r.left, value);
}
return r;
}
This means that you only have to call it like tree.Insert(x).
I was working on a coding problem which required me to find the path to a node. Using recursion and DFS, this was quite easy.
public ArrayList<Integer> ancestorsList = new ArrayList<Integer>();
public boolean printAncestors(TreeNode root, int nodeData) {
if (root == null) return false;
if (root.data == nodeData) return true;
boolean found = printAncestors(root.left, nodeData) || printAncestors(root.right, nodeData);
if (found) ancestorsList.add(root.data);
return found;
}
However, I always had trouble converting a recursive algorithm to a iterative one even though recursion is just using the program stack. I played around with the code a bit, but it seems like the iterative algorithm would require a map that links the child node to it's parent in order to backtrack if the node is found.
I was just wondering if there was a simpler way, or if the simplest way really was using a map that linked the parent and child nodes so you could backtrack.
Thanks!
In order to make code simple,i assume the node is different each other by value.
Basic data structure:
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class TreeNode implements Comparator<TreeNode> {
private int value;
private TreeNode left;
private TreeNode right;
#Override
public int compare(TreeNode o1, TreeNode o2) {
return o1.getValue() - o2.getValue();
}
}
The code to find path:
private static List<TreeNode> findPath(TreeNode root, int val) {
if (null == root) {
return Collections.emptyList();
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
List<TreeNode> path = new ArrayList<>();
while (!stack.isEmpty()) {
TreeNode top = stack.pop();
path.add(top);
// check the value
if (top.getValue() == val) {
break;
}
if (top.getRight() != null) {
stack.push(top.getRight());
}
if (top.getLeft() != null) {
stack.push(top.getLeft());
}
// if the node is leaf,we need rollback the path
if (null == top.getLeft() && null == top.getRight()) {
if (stack.isEmpty()) {
path.clear();
break;
}
TreeNode nextTop = stack.peek();
for (int i = path.size() - 1; i >= 0; i--) {
if (path.get(i).getRight() == nextTop || path.get(i).getLeft() == nextTop) {
path = path.subList(0, i + 1);
break;
}
}
}
}
return path;
}
Test Case:
#Test
public void test_findPath() {
TreeNode treeNode8 = new TreeNode(8, null, null);
TreeNode treeNode9 = new TreeNode(9, null, null);
TreeNode treeNode10 = new TreeNode(10, null, null);
TreeNode treeNode4 = new TreeNode(4, treeNode8, null);
TreeNode treeNode5 = new TreeNode(5, treeNode9, treeNode10);
TreeNode treeNode2 = new TreeNode(2, treeNode4, treeNode5);
TreeNode treeNode1 = new TreeNode(1, treeNode2, null);
List<TreeNode> path = TreeNodeService.findPath(treeNode1, 10);
Assert.assertEquals(path.size(),4);
Assert.assertEquals(path.get(0).getValue(),1);
Assert.assertEquals(path.get(1).getValue(),2);
Assert.assertEquals(path.get(2).getValue(),5);
Assert.assertEquals(path.get(3).getValue(),10);
}
Note: If you tree has two or more nodes has the same value,you need to change some codes.You can try youself.
I'm trying to write a function that displays the height of my binary search tree which is displayed below. The problem is I'm supposed to write a function that doesn't have any arguments or parameters. This is really stumping me. I tried declaring root outside the parameter list but that didn't work. Any solutions?
int height (Node root){
if (root == null) {
return 0;
}
int hleftsub = height(root.m_left);
int hrightsub = height(root.m_right);
return Math.max(hleftsub, hrightsub) + 1;
}
the method signature provide by my instructor is
int height ()
EDIT:
my full code
import javax.swing.tree.TreeNode;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.ArrayList;
class BinarySearchTree<E extends Comparable<E>> {
public Node<E> root;
public int m_size = 0;
public BinarySearchTree() {
}
public boolean search(E value) {
boolean ret = false;
Node<E> current = root;
while (current != null && ret != true) {
if (current.m_value.compareTo(current.m_value) == 0) {
ret = true;
} else if (current.m_value.compareTo(current.m_value) > 0) {
current = current.m_left;
} else {
current = current.m_right;
}
}
return false;
}
public boolean insert(E value) {
if (root == null) {
root = new Node<>(value);
m_size++;
} else {
Node<E> current = root;
Node<E> parentNode = null;
while (current != null)
if (current.m_value.compareTo(value) > 0) {
parentNode = current;
current = current.m_left;
} else if (current.m_value.compareTo(value) < 0) {
parentNode = current;
current = current.m_right;
} else {
return false;
}
if (current.m_value.compareTo(value) < 0) {
parentNode.m_left = new Node<>(value);
} else {
parentNode.m_right = new Node<>(value);
}
}
m_size++;
return true;
}
boolean remove(E value) {
if (!search(value)) {
return false;
}
Node check = root;
Node parent = null;
boolean found = false;
while (!found && check != null) {
if (value.compareTo((E) check.m_value) == 0) {
found = true;
} else if (value.compareTo((E) check.m_value) < 0) {
parent = check;
check = check.m_left;
} else {
parent = check;
check = check.m_right;
}
}
if (check == null) {
return false;
} else if (check.m_left == null) {
if (parent == null) {
root = check.m_right;
} else if (value.compareTo((E) parent.m_value) < 0) {
parent.m_left = check.m_right;
} else {
parent.m_right = check.m_right;
}
} else {
Node<E> parentofRight = check;
Node<E> rightMost = check.m_left;
while (rightMost.m_right != null) {
parentofRight = rightMost;
rightMost = rightMost.m_right;
}
check.m_value = rightMost.m_value;
if (parentofRight.m_right == rightMost) {
rightMost = rightMost.m_left;
} else {
parentofRight.m_left = rightMost.m_left;
}
}
m_size--;
return true;
}
int numberNodes () {
return m_size;
}
int height (Node root){
if (root == null) {
return 0;
}
int hleftsub = height(root.m_left);
int hrightsub = height(root.m_right);
return Math.max(hleftsub, hrightsub) + 1;
}
int numberLeafNodes(Node node){
if (node == null) {
return 0;
}
else if(node.m_left == null && node.m_right == null){
return 1;
}
else{
return numberLeafNodes(node.m_left) + numberLeafNodes(node.m_right);
}
}
void display(String message){
if(root == null){
return;
}
display(String.valueOf(root.m_left));
display(String.valueOf(root));
display(String.valueOf(root.m_right));
}
}
class Node<E> {
public E m_value;
public Node<E> m_left;
public Node<E> m_right;
public Node(E value) {
m_value = value;
}
}
If you traverse the tree iteratively, you can get the height without recursion. Anything recursive can be implemented iteratively. It may be more lines of code though. This would be a variation of level order graph / tree traversal.
See: https://www.geeksforgeeks.org/iterative-method-to-find-height-of-binary-tree/
If you use that implementation, delete the parameter, as height() will already have access to root.
This however requires a queue and is O(n) time and O(n) space.
height() may be a public method that calls a private method height(Node node) that starts recursion. O(n) time, O(1) space for BST.
You can pass height as an extra parameter where recursively inserting into the tree so that you are counting the number of recursive calls (which is directly correlated with the depth / # of levels down in the tree you are). Once a node finds it's place, if the height (# of recursive calls) you were passing exceeds the instance variable height stored by the tree, you update the instance variable to the new height. This will also allow tree.height() to be a constant time function. O(1) time, O(1) space.
I was doing this exercice:
Write code to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. Example input: 3 -> 5 -> 8 -> 5 -> 10 -> 2 -> 1 output: 3 -> 1 -> 2 -> 10 -> 5 -> 5 -> 8
I found it hard to find a solution for Singly linked list (that created by my own, not using library), I would like to know if there is uncessary code blocks in my code and is there a way to avoid putting in two lists and then merge? because it seems to have very slow performance like that.
public CustomLinkedList partition(CustomLinkedList list, int x) {
CustomLinkedList beforeL = new CustomLinkedList();
CustomLinkedList afterL = new CustomLinkedList();
LinkedListNode current = list.getHead();
while (current != null) {
if (current.getData() < x) {
addToLinkedList(beforeL, current.getData());
} else {
addToLinkedList(afterL, current.getData());
}
// increment current
current = current.getNext();
}
if (beforeL.getHead() == null)
return afterL;
mergeLinkedLists(beforeL, afterL);
return beforeL;
}
public void addToLinkedList(CustomLinkedList list, int value) {
LinkedListNode newEnd = new LinkedListNode(value);
LinkedListNode cur = list.getHead();
if (cur == null)
list.setHead(newEnd);
else {
while (cur.getNext() != null) {
cur = cur.getNext();
}
cur.setNext(newEnd);
cur = newEnd;
}
}
public void mergeLinkedLists(CustomLinkedList list1, CustomLinkedList list2) {
LinkedListNode start = list1.getHead();
LinkedListNode prev = null;
while (start != null) {
prev = start;
start = start.getNext();
}
prev.setNext(list2.getHead());
}
CustumLinkedList contains two attributes: -LinkedListNode which is the head and an int which is the size.
LinkedListNode contains two attributes: One of type LinkedListNode pointing to next node and one of type int: data value
Thank you.
The problem of your code is not merging two lists as you mentioned. It's wrong to use the word merge here because you're only linking up the tail of the left list with head of right list which is a constant time operation.
The real problem is - on inserting a new element on the left or right list, you are iterating from head to tail every time which yields in-total O(n^2) operation and is definitely slow.
Here I've wrote a simpler version and avoid iterating every time from head to insert a new item by keeping track of the current tail.
The code is very simple and is definitely faster than yours(O(n)). Let me know if you need explanation on any part.
// I don't know how your CustomLinkedList is implemented. Here I wrote a simple LinkedList node
public class ListNode {
private int val;
private ListNode next;
public ListNode(int x) {
val = x;
}
public int getValue() {
return this.val;
}
public ListNode getNext() {
return this.next;
}
public void setNext(ListNode next) {
this.next = next;
}
}
public ListNode partition(ListNode head, int x) {
if(head == null) return null;
ListNode left = null;
ListNode right = null;
ListNode iterL = left;
ListNode iterR = right;
while(iter != null) {
if(iter.getValue() < x) {
iterL = addNode(iterL, iter.getValue());
}
else {
iterR = addNode(iterR, iter.getValue());
}
iter = iter.getNext();
}
// link up the left and right list
iterL.setNext(iterR);
return left;
}
public ListNode addNode(ListNode curr, int value) {
ListNode* newNode = new ListNode(value);
if(curr == null) {
curr = newNode;
} else {
curr.setNext(newNode);
curr = curr.getNext();
}
return curr;
}
Hope it helps!
If you have any list of data, access orderByX Method.
Hope it would help you.
public class OrderByX {
Nodes root = null;
OrderByX() {
root = null;
}
void create(int[] array, int k) {
for (int i = 0; i < array.length; ++i) {
root = insert(root, array[i]);
}
}
Nodes insert(Nodes root, int data) {
if (root == null) {
root = new Nodes(data);
} else {
Nodes tempNew = new Nodes(data);
tempNew.setNext(root);
root = tempNew;
}
return root;
}
void display() {
Nodes tempNode = root;
while (tempNode != null) {
System.out.print(tempNode.getData() + ", ");
tempNode = tempNode.getNext();
}
}
void displayOrder(Nodes root) {
if (root == null) {
return;
} else {
displayOrder(root.getNext());
System.out.print(root.getData() + ", ");
}
}
Nodes orderByX(Nodes root, int x) {
Nodes resultNode = null;
Nodes lessNode = null;
Nodes greatNode = null;
Nodes midNode = null;
while (root != null) {
if (root.getData() < x) {
if (lessNode == null) {
lessNode = root;
root = root.getNext();
lessNode.setNext(null);
} else {
Nodes temp = root.getNext();
root.setNext(lessNode);
lessNode = root;
root = temp;
}
} else if (root.getData() > x) {
if (greatNode == null) {
greatNode = root;
root = root.getNext();
greatNode.setNext(null);
} else {
Nodes temp = root.getNext();
root.setNext(greatNode);
greatNode = root;
root = temp;
}
} else {
if (midNode == null) {
midNode = root;
root = root.getNext();
midNode.setNext(null);
} else {
Nodes temp = root.getNext();
root.setNext(midNode);
midNode = root;
root = temp;
}
}
}
resultNode = lessNode;
while (lessNode.getNext() != null) {
lessNode = lessNode.getNext();
}
lessNode.setNext(midNode);
while (midNode.getNext() != null) {
midNode = midNode.getNext();
}
midNode.setNext(greatNode);
return resultNode;
}
public static void main(String... args) {
int[] array = { 7, 1, 6, 2, 8 };
OrderByX obj = new OrderByX();
obj.create(array, 0);
obj.display();
System.out.println();
obj.displayOrder(obj.root);
System.out.println();
obj.root = obj.orderByX(obj.root, 2);
obj.display();
}
}
class Nodes {
private int data;
private Nodes next;
Nodes(int data) {
this.data = data;
this.next = null;
}
public Nodes getNext() {
return next;
}
public void setNext(Nodes next) {
this.next = next;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
I think that maintaining two lists is not an issue. It is possible to use a single list, but at the cost of loosing some of the simplicity.
The principal problem seems to be the addToLinkedList(CustomLinkedList list, int value) method.
It iterates throughout the entire list in order to add a new element.
One alternative is to always add elements at the front of the list. This would also produce a valid solution, and would run faster.
NOTICE: this is homework-related, but I'm not tagging it as such because the 'homework' tag is marked as obselete (?)
Using the following class that implements a binary tree...
class TreeNode
{
private Object value;
private TreeNode left, right;
public TreeNode(Object initValue)
{
value = initValue;
left = null;
right = null;
}
public TreeNode(Object initValue, TreeNode initLeft, TreeNode initRight)
{
value = initValue;
left = initLeft;
right = initRight;
}
public Object getValue()
{
return value;
}
public TreeNode getLeft()
{
return left;
}
public TreeNode getRight()
{
return right;
}
public void setValue(Object theNewValue)
{
value = theNewValue;
}
public void setLeft(TreeNode theNewLeft)
{
left = theNewLeft;
}
public void setRight(TreeNode theNewRight)
{
right = theNewRight;
}
}
I need to calculate the number of nodes in the binary tree that are "only children," this being defined as a node that doesn't have another node stemming from its parent.
This is what I have so far:
public static int countOnlys(TreeNode t)
{
if(t == null)
return 0;
if(isAnOnlyChild(t))
return 1;
return countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
I don't know how to implement the boolean method isAnOnlyChild(TreeNode t)
Could someone please help me?
You are pretty close and have the traversal looking good but in your Treenode you do not have a link between a child and its parent. So You can not tell from say a left child if a sibling (right child) exists.
You could have a parent Treenode (along with left and right) so you could check how many children a given node's parent has. Or as ajp15243 suggested, instead use a method that checks how many children a given node has.
Some pseudo code of the latter:
//we still need to check if that only child has its own children
if hasOnlyChild(t)
return 1 + checkOnlys(left) + checkOnlys(right)
else
return checkOnlys(left) + checkOnlys(right)
As you have already noticed, one solution is to count number of parents that have only one child. This should work:
public static int countOnlys(TreeNode t)
{
if(t == null || numberOfChildren(t)==0){
return 0;
}
if(numberOfChildren(t)==1){
return 1+ countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
if(numberOfChildren(t)==2 ){
return countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
return 0;
}
public static int numberOfChildren (TreeNode t){
int count = 0;
if(t.getLeft() != null ) count++;
if(t.getRight() != null) count++;
return count;
}
A parent has an only child if exactly one of the children is non-null (which implies that exactly one of its children is null):
((t.getLeft() == null || t.getRight() == null)) && !(t.getLeft() == null && t.getRight() == null)
You don't test, however, the node when you visit it as the recursive code traverses the tree. (This is similar to the Visitor pattern.) What you do is test for an only child when you are sitting on the parent. It's actually a logical exclusive-or test because one and only one of the children needs to be non-null to detect that this node has an only child.
So the algorithm is to
visit each node in the tree.
count it, if the node has only one child
That's it. The rest is plumbing.
public static int onlyChild(TreeNode t){
int res = 0;
if( t != null){
// ^ means XOR
if(t.getLeft() == null ^ t.getRight() == null){
res = 1;
}
res += onlyChild(t.getLeft()) + onlyChild(t.getRight()));
}
return res;
}
whenever you traverse a binary tree, think recursively. this should work.
public static int countOnlys(TreeNode t)
{
if(t == null)
return 0;
if (t.getLeft()==null&&t.getRight()==null)
return 1;
return countOnlys(t.getLeft())+countOnlys(t.getRight());
}
public int countNode(Node root) {
if(root == null)
return 0;
if(root.leftChild == null && root.rightChild == null)
return 0;
if(root.leftChild == null || root.rightChild == null)
return 1 + countNode(root.leftChild) + countNode(root.rightChild);
else
return countNode(root.leftChild) + countNode(root.rightChild);
}