Thank you for reading my topic. I am practising a little bit with C# at Test Dome. The exercise I am currently trying to program is the following:
http://www.testdome.com/Questions/Csharp/BinarySearchTree/484?testId=21&testDifficulty=Hard
My current result:
Example case: Correct answer
Simple cases: Correct answer
Regular cases: Wrong answer
Edge cases: Wrong answer
Performance test: Wrong answer
You can read the code I wrote so far below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
public class Node
{
public int Value { get; set; } // Value of {node} == integer (1,2,3,4,5)
public Node Left { get; set; } // Reference to left node (n1, n2, n3) == Node.
public Node Right { get; set; } // Reference to right node (n1, n2, n3) == Node.
public Node(int value, Node left, Node right)
{
Value = value; // (int)
Left = left; // (node)
Right = right; // (node)
}
}
public class BinarySearchTree
{
public static bool IsValidBST(Node root)
{
if (root.Left == null && root.Right == null)
return true;
else if (root.Left == null)
{
// Checking root.Right.Value
if (root.Value <= root.Right.Value)
return true;
else
return false;
}
else if (root.Right == null)
{
// Checking root.Left.Value
if (root.Value > root.Left.Value)
return true;
else
return false;
}
else
{
// Checking both Values
if (root.Value > root.Left.Value && root.Value <= root.Right.Value)
return true;
else
return false;
}
}
public static void Main(string[] args)
{
Node n1 = new Node(1, null, null);
Node n3 = new Node(3, null, null);
Node n2 = new Node(2, n1, n3);
// Execute function and write it to the console
Console.WriteLine(IsValidBST(n2));
Console.ReadLine();
}
}
I have no idea what to implement to pass the test. I don't want you to give me written-code, but more information about the exercice. Keep in mind that my current-code is far from neat. Thank you all.
You are not checking all upper nodes values. You should have array/list of all upper nodes, so you can check it.
And also you should use recursion call.
Like this
IsValidBST(Node root, List<int> upperValues = null)
{
...
bool childIsValid = IsValidBST (root.Left, upperValuesLeft ) && IsValidBST(root.Right, upperValuesRight )
}
You should check those other nodes root.Left and root.Right by calling IsValidBST on them if they are not null and then checking these results. Right now you only test the root node instead of descending into the tree
The answer code:
if (root.Value == value) return true;
if (root.Left != null && value < root.Value)
if (Contains(root.Left, value)) return true;
if (root.Right != null && value > root.Value)
if (Contains(root.Right, value)) return true;
return false;
Read my post of the same question.
Related
Recently I had an interview question about finding an element in a binary tree. I coded both recursive and iterative solutions with C# but the problem was that in test cases when we have a tree with 1000000 nodes and all of them are on the left side. The interviewer said to me that my solutions (recursive and iterative) didn't save memory RAM enough for this case and I don't understand how to improve my solution.
// recusive Mode
public Node Find(int v)
{
if(v == value)
{
return this;
}else if(v <value){
if (left == null) return null;
return left.Find(v);
}else{
if (right == null) return null;
return right.Find(v);
}
}
// iterative
public Node Find(int v)
{
Node current = this;
while(value != v && current != null)
{
if (v < current.value)
{
if (current.left == null){ current = null};
else{current = current.left};
}
else
{
if (current.right == null) { current = null};
else{current = current.right };
}
}
return current;
}
Your iterative solution has some bugs in it.
// iterative
public Node Find(int v)
{
Node current = this;
// Here you need to compare current.value instead of just value
// Also, to use short-circuiting you need to put null-check first
// otherwise you might access current.value while current is null
while(current != null && current.value != v)
{
if (v < current.value)
{
//if (current.left == null){ current = null};
//else{current = current.left};
current = current.left; // the same as two commented out lines
}
else
{
//if (current.right == null) { current = null};
//else{current = current.right };
current = current.right; // the same as two commented out lines
}
}
return current;
}
hi I tried to this but its not work , I need to write operation that return true if all leaves in the tree equal to their parents value , please help I have test , maybe its a Main Problem?
Main:
static void Main(string[] args)
{
BinNode<int> t1, t2, bt1, bt2, bt;
t1 = new BinNode<int>(3);
t2 = new BinNode<int>(3);
t2.SetLeft(new BinNode<int>(null, 3, new BinNode<int>(3)));
bt1 = new BinNode<int>(t1, 3, t2);
bt1 = new BinNode<int>(null, 3, bt1);
t1 = new BinNode<int>(3);
t2 = new BinNode<int>(3);
t2.SetLeft(new BinNode<int>(3));
t2.SetRight(new BinNode<int>(new BinNode<int>(3), 3, null));
bt2 = new BinNode<int>(t1, 3, t2);
bt = new BinNode<int>(bt1, 3, bt2);
Console.WriteLine(SumTree(bt));
Console.WriteLine(LeafCounter(bt));
Console.WriteLine(CountWhoHasTwoSameSons(bt));
Console.WriteLine(IsLeafEqualHisFather(bt));
Console.ReadLine();
}
Operation:
public static bool IsLeafEqualHisFather(BinNode<int> Head)
{
if (Head != null)
{
if (IsLeaf(Head))
return true;
if (IsLeaf(Head.GetRight()) == true && (Head.GetRight().GetValue() == Head.GetValue()) || IsLeaf(Head.GetLeft()) == true && (Head.GetLeft().GetValue() == Head.GetValue()))
{
return IsLeafEqualHisFather(Head.GetRight()) && IsLeafEqualHisFather(Head.GetLeft());
}
}
return false;
}
Basically you need to first check if the given node is null or a leaf. If not then you need to determine if the left and right nodes are null and if not if they are leaves or sub-trees. If they are leaves then you need to compare the value to the head, or if they are sub-trees you need to recursively call the method on the sub-tree.
public static bool AllLeavesEqualToParent(BinNode<int> Head)
{
if (Head == null)
return false; // no leaves and no parent.
if (IsLeaf(Head))
return false; // head is a leaf, so there is no parent.
var right = head.GetRight();
var left = head.GetLeft();
if(left != null)
{
if (IsLeaf(left))
{
if (left.GetValue() != Head.GetValue())
return false; // left leaf didn't match
}
else if(!AllLeavesEqualToParent(left))
return false; // left sub tree has leaf that doesn't match parent.
}
if(right!= null)
{
if (IsLeaf(right))
{
if (right.GetValue() != Head.GetValue())
return false; // right leaf didn't match
}
else if(!AllLeavesEqualToParent(right))
return false; // right sub tree has leaf that doesn't match parent.
}
return true; //Both left and right are either null (but not both), a leaf that matches
// the head, or sub trees with all leaves that match their parents.
}
It looks like the main issue here is that you only perform the recursive check if that whole big if expression evaluates to true. But that will only be true if you're already looking at leaves, so if you're starting at the top of a large tree, you're out of look.
Let's simplify it - check whether the left passes the test. This means one of the following:
1. The left node is null
2. The left node is a leaf and has the same value as the current node
3. The left node is not a leaf and passes the IsLeafEqualHisFather test.
The repeat the same for the right. Then check whether they both passed or not.
Side note: there is (almost) never to use [something] == true. [something] serves that purpose all on its own.
public static bool IsLeafEqualHisFather(BinNode<int> current)
{
if (current != null)
{
if (IsLeaf(current))
{
return true;
}
var currentValue = current.GetValue();
var left = current.GetLeft();
var leftPasses = left == null ||
IsLeaf(left) ? left.GetValue() == currentValue : IsLeafEqualHisFather(left);
var right = current.GetRight();
var rightPasses = right == null ||
IsLeaf(right) ? left.GetValue() == currentValue : IsLeafEqualHisFather(left));
return leftPasses && rightPasses;
}
return false;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
class node
{
public int data;
public node next;
public node(int value)
{
next = null;
data = value;
}
public void addFront(node head, int value)
{
var tempNode = new node(value);
tempNode.next = head;
head = tempNode;
}
public void addBack(node head, int value)
{
var insertNode = new node(value);
var traverseNode = head;
while (traverseNode != null)
{
if (traverseNode.next == null)
{
traverseNode.next = insertNode;
insertNode.data = value;
}
traverseNode = traverseNode.next;
}
}
public void printList(node head)
{
var counter = 0;
var traverseNode = head;
while (traverseNode != null)
{
Console.WriteLine("LL item {0}: {1}", counter, traverseNode.data);
traverseNode = traverseNode.next;
counter++;
}
}
public int deleteFront(node head)
{
//Don't need to delete the memory because the garbage collector handles that in c# (at least by my understanding). If this were C, I'd have to use free, and in C++ I'd use keyword Delete
var returnValue = head.data;
head = head.next;
return returnValue;
}
public int deleteBack(node head)
{
node traverseNode = head;
node traverseNodeTrailer = head;
if (traverseNode == null)
{
return 0;
}
while (traverseNode != null)
{
if (traverseNode.next == null)
{
traverseNodeTrailer.next = null;
break;
}
traverseNodeTrailer = traverseNode;
traverseNode = traverseNode.next;
}
return traverseNode.data;
}
public void deleteMiddle(node middleNode)
{
var traverseNode = middleNode;
while (traverseNode != null)
{
if (traverseNode.next.next == null)
{
traverseNode.data = traverseNode.next.data;
traverseNode.next = null;
break;
}
traverseNode.data = traverseNode.next.data;
traverseNode = traverseNode.next;
}
}
public node search(node head, int value)
{
var traverseNode = head;
while (traverseNode != null)
{
if (traverseNode.data == value)
return traverseNode;
traverseNode = traverseNode.next;
}
return null;//failed to find the value in the linked list
}
}
static void Main(string[] args)
{
Int32 userMenuInput = 0;
var running = true;
int userNodeInput = 0;
node head = null;
while (running)
{
Console.WriteLine("Enter a number depending on the operation you would like to perform.");
Console.WriteLine("1 - Insert node of specified value; 2 - Delete a node and return the value; 3 - Search for a node with a specified value; 4 - Print the list values. *All other values exit");
userMenuInput = Convert.ToInt32(Console.ReadLine());//get user input for what they want to do
switch (userMenuInput)
{
case 1:
Console.WriteLine("Enter a number you'd like to insert into the linked list.");
userNodeInput = Convert.ToInt32(Console.ReadLine());//get user input for value to insert
if (head == null)
{
head = new node(userNodeInput);
break;
}
head.addFront(head, userNodeInput);
break;
case 2:
if (head == null)
{
Console.WriteLine("The list is empty - cannot delete.");
break;
}
userNodeInput = head.deleteFront(head);
Console.WriteLine("{0} is the value that was deleted from the front of the list.", userNodeInput);
break;
case 3:
Console.WriteLine("What is the value you'd like to search for in the list?");
userNodeInput = Convert.ToInt32(Console.ReadLine());
if (head == null)
{
//do nothing
}
else if (head.search(head, userNodeInput) != null)
{
Console.WriteLine("That value was found");
break;
}
Console.WriteLine("That value was not found.");
break;
case 4:
if (head == null)
{
Console.WriteLine("The list has nothing to print.");
break;
}
head.printList(head);
break;
default:
running = false;
break;
}
}
}
}
}
DISCLAIMER: I'm very new to c# - just been using it for the past week or so. I will appreciate any optimization hints you have, but for now, I'm just trying to get this running.
So, this is correctly inserting 1 element, but nothing more. It is finding the element if it is in the first link. The delete doesn't seem to be working at all. It doesn't throw any errors but it also doesn't delete the first link. Note: A few of my functions in there are unused so far so don't worry about mentioning that - I'm aware.
Thanks everyone!
You can use ref if you want to modify argument passed to addFront method:
public void addFront(ref node head, int value)
{
var tempNode = new node(value);
tempNode.next = head;
head = tempNode;
}
.
head.addFront(ref head, userNodeInput);
I created a LinkedList class with a function delete to remove a certain node from the list if found, however it's not working:
public class LinkedList
{
public Node head;
<...>
public void delete(string n)
{
Node x = search(n); //returns the node to delete or null if not found
if (x != null)
x = x.next;
}
<...>
}
I figured all I needed to do is find the node and set it to the next one (so the node is "removed" out of the linked list), however it's not. If anyone could help me out it'd be much appreciated!
EDIT: Forgot to mention I have a single linked list.
EDIT2: My new code:
public void delete(string n)
{
Node x = head;
while (x != null && x.name != n)
{
if (x.next.name == n)
x.next = x.next.next;
x = x.next;
}
if (x != null)
x = null;
}
You'll want to loop through the list until the next node is the one you want to delete. Then set the current to the next nodes next node.
public void Delete(string value)
{
if (head == null) return;
if (head.Value == value)
{
head = head.Next;
return;
}
var n = head;
while (n.Next != null)
{
if (n.Next.Value == value)
{
n.Next = n.Next.Next;
return;
}
n = n.Next;
}
}
This of course assumes you only want to delete the first match.
How do I print out a given node from my binary search tree using a method called PrintNodes.
Here is my Node class:
public class Node
{
public string data;
public Node left;
public Node right;
public Node(string data)
{
this.data = data;
}
}
And here is my Binary Search Tree Class:
class BinarySearchTree
{
public Node root, current;
public BinarySearchTree()
{
this.root = null;
}
public void AddNode(string a) // code to insert nodes to the binary search tree
{
Node newNode = new Node(a); //create a new node
if (root == null) // if the tree is empty new node will be the root node
root = newNode;
else
{
Node previous;
current = root;
while (current != null)
{
previous = current;
if (string.Compare(a, current.data) < 0) //if the new node is less than the current node
{
current = current.left;
if (current == null)
previous.left = newNode;
}
else //if the new node is greater than the current node
{
current = current.right;
if (current == null)
previous.right = newNode;
}
}
}
}
This is the what I have so far for my PrintNodes method, but I just realised that its not actually printing the given node its just printing the string that I pass into the method(I'm really new to this as you can see)
public String PrintNodes(string a)
{
string Output = "";
if (a != null)
{
Output += "Node: " + a;
}
else
{
Output += "There is no node " + a;
}
return Output;
}
I know I have to somehow compare the string that is passed into the method to the node I am trying to print but I have no clue what to do my mind has gone blank.
Your Find method would look something like this:
public Node Find(key, root)
{
Node current-node = root;
while (current-node != null)
{
if (current-node.data == key)
return current-node;
else if (key < current-node.data)
current-node = current-node.left;
else
current-node = current-node.right;
}
return null;
}
Your PrintNodes method could then be:
public String PrintNodes(string a)
{
string Output = "";
Node theNode = Find(a);
if (Node != null)
{
Output += "Node: " + theNode.data;
}
else
{
Output += "There is no node " + a;
}
return Output;
}
Cheers
EDIT: I assume that your Node object will have some other "payload" attached to it, as right now you're simply printing the search string if found :-)
I believe that you need to find some string in the tree and print it.
if it is
here is a pseudo code
public String PrintNodes(string a , Node root)
{
string Output = "";
if( a == null )
return "string is empty";
Node curent;
curent = root;
while( curent != null )
{
compVal = string.Compare(a, current.data)
if ( compVal < 0 )
{
//goto leftNode
curent = curent.left
}
else if ( compVal > 0 )
{
//goto rightNode
curent = curent.right
}
else
{
//this is it
break;
}
}
if curent == null
return "string not found";
else
return
curent.data;
}