check whether binary tree is balanced or not? - algorithm

I was working on the problem of checking the height of the balanced binary tree and found one tutorial like
if (height of left subtree == -1)
return -1.
public boolean isBalanced(TreeNode root) {
if (root == null){
return true;
}
return height(root) != -1;
}
int height(TreeNode node){
`if (node == null){`
return 0;
}
int left = height(node.left);
int right = height(node.right);
int bf = Math.abs(left- right);
if (bf \> 1 || left == -1 || right == -1){
return -1;
}
return Math.max(left,right)+1;
}
So, I was wondering in what case the height of the left subtree of the binary tree will be -1?
Thank you
I looked over the tutorial and it was not explained properly.

Consider a tree. Which has a root and a child in left. Its child on left has only child on left and no right child and so on.
R
/
C0
/
C1
/
C2
/
C3
Height is called with root R. Now Root R calls height on its left child C0 and right child (NULL).
C0 does this to C1 then C1 does this same thing on C2 and so on.
So we'll calculate from C3 then to C2 then to C1, because that's how recursion is going to get executed.
In your function height(C3) now we call its height(C3->left) and height(C3->right). Both are NULL. Left and Right for them = 0.
Height(C3) returns 1. As
(Math.max(left,right)+1; => Math.max(0,0)+1; => 1)
Now For function call height(C2)
left = Height(C2->left) i.e. C3
//hence left = 1;
right = Height(C2->right) i.e. NULL
//hence right = 0;
bf = Math.abs(left-right); => Math.abs(1-0); => 1
still all conditions are false and we return:
Math.max(left,right)+1; => Math.max(1,0)+1; => 2
Now let's come to height(C1)
left = height(C1->left) i.e. height(C2)
//left = 2
right = height(C1->right) i.e. height(NULL)
//right = 0
Now,
bf = Math.abs(left-right); => bf = Math.abs(2-0); => bf = 2
since bf > 1 now, the if condition is executed and you return -1.
Now, for height(C0)
left = height(C0->left); => height(C1)
left = -1 //this is where you get height = -1
Now from this point above all your returns will be -1 because of the condition. Saying that this tree is not balanced.

Related

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.

A structure to represent an ordered set of disjoint segments

I have an ordered set of disjoint segments
S = {[a1 b1] [a2 b2] ... [an bn]}
with b1 + 1 < a2, b2 + 1 < a3, etc. All numbers are integers.
I am seeking for a data structure to represent that set with an insert operation. I know that there's no intersection between the inserting segment [a b] and the segments from S, but a merge may be needed if b + 1 = ak or bk + 1 = a for some k.
How about a linked list where the value at each node is a pair of integers.
We need a slightly modified insert operation, let's call it insertAndMerge.
def insertAndMerge(segment, head) {
curr = head;
// find element to insert after
while (segment.a < curr.b) {
curr = curr.next;
}
// if bk + 1 = a case occurs, merge with existing element, otherwise insert the new one
if (curr.b + 1 = segment.a) {
curr.b = segment.b;
} else {
segment.next = curr.next;
curr.next = segment;
curr = curr.next;
}
// the insertion or merge above could trigger the b + 1 = ak case, necessitating a merge with the element after it
if (curr.b + 1 = curr.next.a) {
toRemove = curr.next;
curr.next = toRemove.next;
curr.b = toRemove.b;
delete toRemove;
}
}

Find close path or region using recursive method

I have a object in 2d array and i want to traverse through them top, left, right for that object acutally i want to check if there are making some loop or better making some closed region. See this picture for better explanation.
Acutally i have a X x Y of slot and when user touch on any of the region it adds the brick there so what i want to do is every time user add a brick check if it is making a close path.
I have writen recursive function for that but it's not working fine it always go for the top only and not right and left. Here is the code
function checkTrap(y,x)
if all_tiles[y][x].state == "changed" then --if brick is added at that location
last_move_y = y
last_move_x = x
--check for top
y = y - 1
if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to top at"..y..", "..x)
return checkTrap(y, x)
end
--check for bottom
y = y + 1
if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to bottom at"..y..", "..x)
return checkTrap(y, x)
end
--check for left
x = x - 1
if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to left at"..y..", "..x)
return checkTrap(y, x)
end
--check for right
x = x + 1
if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to right at"..y..", "..x)
return checkTrap(y, x)
end
elseif all_tiles[y][x] == object then
print("it's a loop"..y..", "..x)
return true;
else
print("not changed")
return false
end
end
Edit : New Solution
function findClosedRegion()
local currFlag, isClose = -1, false
local isVisited = {
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1}}
local k, m = 1, 1
while k <= 6 and not isClose
do
print("K "..k)
while m <= 6 and not isClose
do
print("M "..m)
if not isBrick[k][m] and isVisited[k][m] == -1 then
local cellsi = Stack:Create()
local cellsj = Stack:Create()
cellsi:push(k)
print("Pushed k "..k)
cellsj:push(m)
print("Pushed m "..m)
currFlag = currFlag + 1
isClose = true
while cellsi:getn() > 0 and isClose do
local p = cellsi:pop()
print("Pop p "..p)
local q = cellsj:pop()
print("Pop q "..q)
if( p >= 1 and p <= 6 and q >= 1 and q <= 6 ) then
if(not isBrick[p][q]) then
print("white ")
if(isVisited[p][q] == -1) then
print("invisited")
isVisited[p][q] = currFlag
cellsi.push(p - 1)
cellsj.push(q)
cellsi.push(p + 1)
cellsj.push(q)
cellsi.push(p)
cellsj.push(q + 1)
cellsi.push(p)
cellsj.push(q - 1)
cellsi:list()
else
if(isVisited[p][q] < currFlag) then
print("visited < currFlag")
isClose = false
end
end
end
else
isClose = false
end --p and q if ends here
end -- tile while end
else
--print("changed and not -1")
end
m = m + 1
end -- m while end
if(isClose) then
print("Closed path")
end
m = 1
k = k + 1
end -- k while end
end
The structure of the implementation does not recurse into other directions as only the first branch is called; somehow all neighbors should be included. Apparently you try to implement a kind of Deph-first search on your array. The approach seems absolutely rightm, but all neighbors of a cell have to be taken into account. What perhaps would help most would be to do a connected component analysis and fill all the connected components which touch the border.
EDITED:
Instead if searching with the help of black cells, we should search with white cells because your goal is to find area bound by black cells, even if diagonally adjacent. We should find a group of white cells which is only bordered by black cells and not by the border of the whole main grid. That should satisfy your purpose.
JS Fiddle: http://jsfiddle.net/4d4wqer2/
This is the revised algorithm I came up with:
for each cell and until closed area not found
if white and visitedValue = -1
push cell to stack
while stack has values and closed area not found
pop cell from stack
if invalid cell // Cell coordinates are invalid
this area is not closed, so break from the while
else
if white
if visitedValue = -1
{
mark visited
push neighboring four cells to the stack
}
else
if visitedValue > currVisitNumber // The current cells are part of previous searched cell group, which was not a closed group.
this area is not closed, so break from the while
if closed area found
show message
Programmed using JQuery:
function findArea() {
var currFlag = -1, isvisited = [], isClosed = false;
for (var k = 0; k < rows; k++) { // Initialize the isvisited array
isvisited[k] = [];
for (var m = 0; m < cols; m++)
isvisited[k][m] = -1;
}
for (var k = 0; k < rows && !isClosed; k++)
for (var m = 0; m < cols && !isClosed; m++) {
if (!isblack[k][m] && isvisited[k][m] == -1) { // Unvisited white cell
var cellsi = [k], cellsj = [m];
currFlag++;
isClosed = true;
while (cellsi.length > 0 && isClosed) { // Stack has cells and no closed area is found
var p = cellsi.pop(), q = cellsj.pop();
if (p >= 0 && p < rows && q >= 0 && q < cols) { // The cell coord.s are valid
if (!isblack[p][q])
if (isvisited[p][q] == -1) {
isvisited[p][q] = currFlag; // Mark visited
cellsi.push(p - 1); // Push the coord.s of the four adjacent cells
cellsj.push(q);
cellsi.push(p + 1);
cellsj.push(q);
cellsi.push(p);
cellsj.push(q + 1);
cellsi.push(p);
cellsj.push(q - 1);
}
else
if (isvisited[p][q] < currFlag) // The current group of white cells was part of a previous group of white cells which were found to be unbound by the black cells. So, skip this group.
isClosed = false;
}
else
isClosed = false; // The current cell is out of border. Hence skip the whole group.
}
}
}
if (isClosed)
alert('Closed area found');
}
JS Fiddle: http://jsfiddle.net/4d4wqer2/

Union Find to solve Traveling Salesman

I have to use the union find algorithm to solve the traveling salesman problem. I prettymuch got it done except for one problem I've just discovered. As it processes each edge, it will check for a cycle, which is done with the whole parent array thing. The problem is that, when it gets to the last edge I need to add to complete the problem, since it is technically a cycle, it does not add the edge, so the path can not be completed. How can I differentiate a useless cycle from the cycle indiicating that we are done?
Here's the code I got so far
private int[] parent; //parent of each vertex
private int[] connection; //number of edges coming from a given vertex
private int[] subsize; //size of each subtree
boolean donepath;
public void GreedyAlgo(){
ArrayList<Edge> newedges = new ArrayList<Edge>();
for(int i = 0; i<graph.realedge.size();i++){
if(donepath) break;
Edge e= graph.realedge.get(i);
int x = e.in1;
int y = e.in2;
if(unionFind(x,y) && !thirdEdge(x,y)){
newedges.add(e);
}
else{
}
}
}
public int findParent(int i){
if (parent[i] != i)
return findParent(parent[i]);
return parent[i];
}
public boolean unionFind(int x, int y){
int xx = findParent(x);
int yy = findParent(y);
if(xx == yy){
if(subsize[xx]== n){
donepath = true;
return true;
}
return false;
}
else{
if( subsize[xx] < subsize[yy]){
parent[xx] = yy;
subsize[yy]+=subsize[xx];
}
else if( subsize[xx] > subsize[yy]){
parent[yy] = xx; subsize[xx]+=subsize[yy];
}
else{
parent[yy] = xx;
subsize[xx]+=subsize[yy];
}
connection[x]++;
connection[y]++;
}
return true;
}
public boolean makesCycle(int x, int y){
int xx = findParent(x);
int yy = findParent(y);
if(xx == yy){
return true;
}
return false;
}
Here are the edges it goes through in order
0-0,
1-1,
2-2,
3-3,
4-4,
0-4 should get added,
2-3 should get added,
3-2,
4-0,
0-1 should get added,
0-2 ,
0-3,
1-0,
1-4,
2-0,
3-0,
4-1,
1-3 should get added,
3-1,
2-4 should get added......but doesnt,
3-4,
4-2,
4-3,
1-2,
2-1,
What about keeping track of the size of each of the sets?
Then, when doing a union, if the root of both is the same (i.e. a cycle) and the root's size equals the sum of all the points in your problem, include that edge and stop, otherwise continue as per usual.
Warning:
Note that a simple Union-Find implementation is likely to end you up with minimum spanning tree rather than a hamiltonian cycle. You need to make sure you pick appropriate edges - I'll assume you've figured that out, or, if not, I'll leave it to you.
Elaboration:
The Union for your problem should look something like: (derived from Wikipedia)
(returning false or true to indicate whether we should add the edge)
boolean Union(x, y)
xRoot = Find(x)
yRoot = Find(y)
if xRoot == yRoot
return false
// merge xRoot and yRoot
xRoot.parent = yRoot
return true
(the proper merge (for efficiency) is a little more complicated - you should compare the depths and pick the deepest one as the parent, see Wikipedia for details)
Now, my suggestion:
Create a size variable for each node, initialized to 1, and then the Union function:
boolean Union(x, y)
xRoot = Find(x)
yRoot = Find(y)
if xRoot == yRoot
// check if it's the last node
if xRoot.size == pointCount
done = true
return true
else
return false
// merge xRoot and yRoot
xRoot.parent = yRoot
yRoot.size += xRoot.size
return true
Example:
Points:
1---2
|\ |
| \ |
| \|
4---3
There are 4 points, thus pointCount = 4
Starting off: (size appears under node)
1 2 3 4
1 1 1 1
Union 1 and 2:
1 3 4
2 1 1
|
2
1
Union 3 and 2:
3 4
3 1
|
1
2
|
2
1
Union 3 and 1:
The common root is 3 (thus xRoot == yRoot is true) and xRoot.size(3) != pointCount(4), thus we return false (don't add the edge).
Union 3 and 4:
4
4
|
3
3
|
1
2
|
2
1
Union 4 and 1:
The common root is 4 (thus xRoot == yRoot is true) and xRoot.size(4) == pointCount(4), thus we return true (add the edge) and we set the flag to indicate that we're done.

Resources