Using recursion to get the sum of a tree, but the root node won't add in Kotlin - algorithm

I'm doing a question to get the sum of an entire tree through recursion, but the root node wont add with the child node. Now I'm aware that the root node is just a value while the child nodes are Tree nodes, so there not the same type.
class TreeNode<T>(var key: T){
var left: TreeNode<T>? = null
var right: TreeNode<T>? = null
}
fun treeSumR(root: TreeNode<Int>): Int{
if (root == null) return 0
return root.key + root.left?.let { treeSumR(it) } + root.right?.let { treeSumR(it) }
}
fun buildTree2(): TreeNode<Int>{
val one = TreeNode(1)
val two = TreeNode(2)
val four = TreeNode(4)
val eleven = TreeNode(11)
val three = TreeNode(3)
val four2 = TreeNode(4)
three.left = eleven
three.right = four
eleven.left = four2
eleven.right = two
four.right = one
return three
}
Any help is appreciated. Thanks.

There is an error on the + operators because you are adding a non-nullable Int (root.key) and nullable Int?s (the sums of the subtrees) together. The sums of the subtrees are nullable because you wrote ?.. Its effect is that the whole expression of root.left?.let { ... } evaluates to null if root.left is null.
You can provide a default value for the expression when it is null by using the elvis operator:
return root.key +
(root.left?.let { treeSumR(it) } ?: 0) +
(root.right?.let { treeSumR(it) } ?: 0)
However, since you are already checking if root is null and returning 0, a better way is to make root actually nullable, and pass root.left and root.right directly into it treeSumR:
// notice the question mark here
// v
fun treeSumR(root: TreeNode<Int>?): Int{
if (root == null) return 0
return root.key +
treeSumR(root.left) + // since treeSumR now takes a nullable node, you can directly pass the subtrees in
treeSumR(root.right)
}

Related

Kotlin linked list: How to check if given list is sorted (descending)

I am trying to write a function, which determines if the given linked list is sorted (descending).
Given list 1: 8 -> 5 -> 3 -> null (true)
Given list2: 8 -> 6 -> 10 -> 3 -> null (false)
Given list3: 8 -> 8 -> 3 -> null (true)
Here is my current approach:
class Linkedlist {
var head: Node? = null
data class Node(val value: Int, var next: Node?)
// Current approach
fun isListSorted(): Boolean {
// If list is empty
if (head == null) return true
var curr = head
while(curr != null) {
curr = curr.next
if (curr?.value!! <= curr?.next?.value!!) return false else return true
}
return true
}
}
And here my main:
fun main() {
val list1 = Linkedlist()
list1.append(8)
list1.append(5)
list1.append(3)
val list2 = Linkedlist()
list2.append(8)
list2.append(6)
list2.append(10)
list2.append(3)
val list3 = Linkedlist()
list3.append(8)
list3.append(8)
list3.append(3)
}
I get a NullPointerException. What am I doing wrong? I appreciate every help!
One of Kotlin's most attractive features is null-safety. You don't get NullPointerExceptions unless you use the !! operator. The !! operator should only be used when you have checked your code and you logically know that at that point in code, the parameter cannot be null, but the logic to figure that out is too much for the compiler.
You use the !! operator in a place where the value of curr very well can be null. You set curr = curr.next, and next will be null at the tail of your list, so curr will be null when you use the !! operator on it.
This line of code wouldn't make sense anyway, because you return from both branches of your if/else here, so you cannot possibly ever check more than one node of your list.
A possible way to do this:
fun isListSorted(): Boolean {
var curr = head ?: return true
while(true) {
val next = curr.next ?: return true
if (curr.value < next.value)
return false
curr = next
}
}

Is there a way to find a path in a tree?

Let's say we have a tree like the one below. Is there an algorithm that given 2 nodes find the path that connects them. For example, given (A,E) it will return [A,B,E], or given (D,G) it will return [D,B,A,C,G]
A
/ \
B C
/ \ / \
D E F G
You will need to have a tree implementation where a child node has a link to its parent.
Then for both nodes you can build the path from the node to the root, just by following the parent link.
Then compare the two paths, starting from the ends of the paths (where the root is): as long as they are the same, remove that common node from both paths.
Finally you are left with two diverting paths. Reverse the second, and join the two paths, putting the last removed node in between the two.
Here is an implementation in JavaScript:
function getPathToRoot(a) {
if (a.parent == null) return [a];
return [a].concat(getPathToRoot(a.parent));
}
function findPath(a, b) {
let p = getPathToRoot(a);
let q = getPathToRoot(b);
let common = null;
while (p.length > 0 && q.length > 0 && p[p.length-1] == q[q.length-1]) {
common = p.pop();
q.pop();
}
return p.concat(common, q.reverse());
}
// Create the example tree
let nodes = {};
for (let label of "ABCDEFG") {
nodes[label] = { label: label, parent: null };
}
nodes.B.parent = nodes.C.parent = nodes.A;
nodes.D.parent = nodes.E.parent = nodes.B;
nodes.F.parent = nodes.G.parent = nodes.C;
// Perform the algorithm
let path = findPath(nodes.E, nodes.G);
// Output the result
console.log("Path from E to G is:");
for (let node of path) {
console.log(node.label);
}

Tree from balanced parenthesis

I have to find height of tree and find protection number (or just to generate a tree) from balanced parentheses.
For example:
()()()() creates tree like a list with height 3.
I have no idea how to convert parentheses to tree. I found some 'answers':
http://www.cs.utsa.edu/~wagner/knuth/fasc4a.pdf (second page contains all examples for tree with 4 nodes)
paragraph - Binary Trees, Forests, Non-Crossing Pairs :
https://sahandsaba.com/interview-question-generating-all-balanced-parentheses.html
However, I still don't know how to create a tree from such defined parentheses. I have some impression that in Knuth, authors treat it as something obvious.
Do I miss something or it's not that simple?
Is it necessary to create a forest and then a binary tree?
A pair of parentheses represents a node. What appears within those parentheses represents its left child's subtree (according to the same rules). What appears at the right of those parentheses represents the node's right child's subtree (again, according to the same rules).
The conversion of this encoding into a binary tree can be done recursively like this:
function makeBinaryTree(input):
i = 0 # character index in input
function recur():
if i >= input.length or input[i] == ")":
i = i + 1
return NIL
i = i + 1
node = new Node
node.left = recur()
if i >= input.length or input[i] == ")":
i = i + 1
return node
node.right = recur()
return node
return recur()
Here is an implementation in JavaScript that performs the conversion for each of those 4-noded trees, and pretty prints the resulting trees:
function makeBinaryTree(input) {
let i = 0; // character index in input
return recur();
function recur() {
if (i >= input.length || input[i++] === ")") return null;
let node = { left: recur(), right: null };
if (i >= input.length || input[i] === ")") {
i++;
return node;
}
node.right = recur();
return node;
}
}
// Helper function to pretty print a tree
const disc = "\u2B24";
function treeAsLines(node) {
let left = [""], right = [""];
if (node.left) left = treeAsLines(node.left);
if (node.right) right = treeAsLines(node.right);
while (left.length < right.length) left.push(" ".repeat(left[0].length));
while (left.length > right.length) right.push(" ".repeat(left[0].length));
let topLeft = "", topRight = "";
let i = left[0].indexOf(disc);
if (i > -1) topLeft = "┌".padEnd(left[0].length-i+1, "─");
i = right[0].indexOf(disc);
if (i > -1) topRight = "┐".padStart(i+2, "─");
return [topLeft.padStart(left[0].length+1) + disc + topRight.padEnd(right[0].length+1)]
.concat(left.map((line, i) => line + " " + right[i]));
}
// The trees as listed in Table 1 of http://www.cs.utsa.edu/~wagner/knuth/fasc4a.pdf
let inputs = [
"()()()()",
"()()(())",
"()(())()",
"()(()())",
"()((()))",
"(())()()",
"(())(())",
"(()())()",
"(()()())",
"(()(()))",
"((()))()",
"((())())",
"((()()))",
"(((())))"
];
for (let input of inputs) {
let tree = makeBinaryTree(input);
console.log(input);
console.log(treeAsLines(tree).join("\n"));
}
If I understood Knuth correctly, the representation works as the following: A pair of matching parentheses represents a node, e.g. () = A. Two consecutive pairs of matching parentheses means that the second node is the right child of the first one, e.g. ()() = A -> B. And two pairs of embedded parentheses means the inside node is the left child of the outside node, i.e. (()) = B <- A. Therefore, ()()()() = A -> B -> C -> D.
A possible algorithm to convert parentheses to binary tree would be:
convert(parentheses):
if parentheses is empty:
return Nil
root = Node()
left_start = 1
left_end = Nil
open = 0
for p = 0 to |parentheses|-1:
if parentheses[p] == '(':
open += 1
else
open -= 1
if open == 0:
left_end = p
break
root.left = convert(parentheses[left_start:left_end] or empty if index out of bound)
root.right = convert(parentheses[left_end+1:] or empty if index out of bound)
return root
It works by converting parentheses (L)R in the binary tree L <- A -> R recursively.

How to best build a persistent binary tree from a sorted stream

For a side project I wanted a simple way to generate a persistent binary search tree from a sorted stream. After some cursory searching I was only able to find descriptions of techniques that involved storing a sorted array where you can access any element by index. I ended up writing something that works but I figured this is well trodden territory and a canonical example is probably documented somewhere (and probably has a name).
The make shift code I made is included just for clarity. (It's also short)
object TreeFromStream {
sealed trait ImmutableTree[T] {
def height: Int
}
case class ImmutableTreeNode[T](
value: T,
left: ImmutableTree[T],
right: ImmutableTree[T]
) extends ImmutableTree[T] {
lazy val height = left.height + 1
}
case class NilTree[T]() extends ImmutableTree[T] {
def height = 0
}
#tailrec
def treeFromStream[T](
stream: Stream[T],
tree: ImmutableTree[T] = NilTree[T](),
ancestors: List[ImmutableTreeNode[T]] = Nil
): ImmutableTree[T] = {
(stream, ancestors) match {
case (Stream.Empty, _) =>
ancestors.foldLeft(tree) { case(right, root) => root.copy(right=right) }
case (_, ancestor :: nextAncestors) if ancestor.left.height == tree.height =>
treeFromStream(stream, ancestor.copy(right=tree), nextAncestors)
case (next #:: rest, _) =>
treeFromStream(
rest, NilTree(),
ImmutableTreeNode(next, tree, NilTree()) :: ancestors
)
}
}
}
To create a balanced tree, which I will guess you want to do, you will need to visit each node at least once. First, collect all the nodes into a buffer, and then recursively convert the buffer into a tree:
def tfs[T](stream: Stream[T]): ImmutableTree[T] = {
val ss = scala.collection.mutable.ArrayBuffer.empty[T]
def treeFromSubsequence(start: Int, end: Int): ImmutableTree[T] =
if (end == start) NilTree()
else if (end - start == 1) ImmutableTreeNode(ss(start), NilTree(), NilTree())
else {
val mid = (end - start) / 2
ImmutableTreeNode(ss(mid), treeFromSubsequence(start, mid), treeFromSubsequence(mid + 1, end))
}
stream.foreach { x => ss += x }
treeFromSubsequence(0, ss.length)
}
It will visit each value exactly twice, once to collect it and once to put it into the value field of a tree.

Maximum element in a tree

I have the following ADT implementation in Scala.
How to find the maximum element in the tree? Can I introduce some helper function, and if yes, then how?
abstract class MySet {
def max: Int
def contains(tweet: Tweet): Boolean = false
}
class Empty extends MySet {
def max: throw new NoSuchElementExeption("max called on empty tree")
def contains(x: Int): Boolean =
if (x < elem) left.contains(x)
else if (elem < x) right.contains(x)
else true
}
class Node(elem: Int, left: MySet, right: MySet) extends Set {
def max: { ... }
def contains(x: Int): Boolean =
if (x < elem) left.contains(x)
else if (elem < x) right.contains(x)
else true
}
I found a solution in Haskell which feels quite intuitive can I convert it to Scala somehow?
data Tree a = Nil | Node a (Tree a) (Tree a)
maxElement Nil = error "maxElement called on empty tree"
maxElement (Node x Nil Nil) = x
maxElement (Node x Nil r) = max x (maxElement r)
maxElement (Node x l Nil) = max x (maxElement l)
maxElement (Node x l r) = maximum [x, maxElement l, maxElement r]
Update
I am not interested in copying the Haskell code in Scala instead I think Haskell version is more intuitive but because of this keyword and other stuff in Object oriented language. How can I write the equivalent code in object oriented style without pattern matching?
Your tree is heterogeneous, which means that each node can be either a full node with a value, or an empty leaf. Hence you need to distinguish which is which, otherwise you can call max on an empty node. There are many ways:
Classic OOP:
abstract class MySet {
def isEmpty: Boolean
...
}
class Empty extends MySet {
def isEmpty = true
...
}
class Node(...) extends MySet {
def isEmpty = false
...
}
So you do something like this:
var maxElem = elem
if(!left.isEmpty)
maxElem = maxElem.max(left.max)
end
if(!right.isEmpty)
maxElem = maxElem.max(right.max)
end
Since JVM has class information at runtime you can skip the definition of isEmpty:
var maxElem = elem
if(left.isInstanceOf[Node])
maxElem = maxElem.max(left.asInstanceOf[Node].max)
end
if(left.isInstanceOf[Node])
maxElem = maxElem.max(right.asInstanceOf[Node].max)
end
(asInstanceOf is not required if you defined max in MySet, but this pattern covers the case when you didn't)
Well, Scala has a syntactic sugar for the latter, and not surprisingly it's the pattern matching:
var maxElem = elem
left match {
case node: Node =>
maxElem = maxElem.max(node.max)
case _ =>
}
right match {
case node: Node =>
maxElem = maxElem.max(node.max)
case _ =>
}
maxElem
You can take it slightly further and write something like this:
def max = (left, right) match {
case (_: Empty, _: Empty) => elem
case (_: Empty, node: Node) => elem.max(node.max)
case (node: Node, _: Empty) => elem.max(node.max)
case (leftNode: Node, rightNode: Node) =>
elem.max(leftNode.max).max(rightNode.max)
}
If you don't want to use pattern matching, you will need to implement an isEmpty operation or its equivalent, to avoid calling max on an empty set.
The important thing is how the tree is organized. Based on the implementation of contains, it looks like you have an ordered tree (a "binary search tree") where every element in the left part is less than or equal to every element in the right part. If that's the case, your problem is fairly simple. Either the right sub tree is empty and the current element is the max, or the max element of the tree is the max of the right sub tree. That should be a simple recursive implementation with nothing fancy required.
Full disclosure, still learning Scala myself, but here is two versions I came up with (which the pattern match looks like a fair translation of the Haskell code)
sealed trait Tree {
def max: Int
def maxMatch: Int
}
case object EmptyTree extends Tree {
def max = 0
def maxMatch = 0
}
case class Node(data:Int,
left:Tree = EmptyTree,
right:Tree = EmptyTree) extends Tree {
def max:Int = {
data
.max(left.max)
.max(right.max)
}
def maxMatch: Int = {
this match {
case Node(x,EmptyTree,EmptyTree) => x
case Node(x,l:Node,EmptyTree) => x max l.maxMatch
case Node(x,EmptyTree,r:Node) => x max r.maxMatch
case Node(x,l:Node,r:Node) => x max (l.maxMatch max r.maxMatch)
}
}
}
Tests (all passing)
val simpleNode = Node(3)
assert(simpleNode.max == 3)
assert(simpleNode.maxMatch == 3)
val leftLeaf = Node(1, Node(5))
assert(leftLeaf.max == 5)
assert(leftLeaf.maxMatch == 5)
val leftLeafMaxRoot = Node(5,
EmptyTree, Node(2))
assert(leftLeafMaxRoot.max == 5)
assert(leftLeafMaxRoot.maxMatch == 5)
val nestedRightTree = Node(1,
EmptyTree,
Node(2,
EmptyTree, Node(3)))
assert(nestedRightTree.max == 3)
assert(nestedRightTree.maxMatch == 3)
val partialFullTree = Node(1,
Node(2,
Node(4)),
Node(3,
Node(6, Node(7))))
assert(partialFullTree.max == 7)
assert(partialFullTree.maxMatch == 7)

Resources