I want to traverse over a given tree using in-order traversal. inserting the sorted array into the BST (keeping it the same shape)
This is my go:
public static BinTreeNode<Integer> ARR_TO_BST(BinTreeNode<Integer> root, int[] arr, int ind){
if (root.GetLeft() != null)
ARR_TO_BST(root.GetLeft(), arr, ind);
root.SetInfo(arr[ind]);
ind+=1;
if (root.GetRight() != null)
ARR_TO_BST(root.GetRight(), arr, ind);
return root;
The problem is that if the array is arr = {10,20,30,40,50,60}
and the tree is:
The return output is a tree that if I do an in-order traversal over it is: 10 20 10 20 10 20 ... and not 10 20 30 40 50 60
I need the output to be the same shape of the picture but with the values of arr the algorithm is to traverse -in order on the tree : left subtree - vertex - right subtree
but instead of reading the values we insert the values from arr to root
I would appreciate help! thank you
You never change ind. After the first call to ARR_TO_BST, it remains what it was before the call. Make ARR_TO_BST return the number of elements it placed:
if (root.GetLeft() != null)
ind = ARR_TO_BST(root.GetLeft(), arr, ind);
root.SetInfo(arr[ind]);
if (root.GetLeft() != null)
ind = ARR_TO_BST(root.GetLeft(), arr, ind + 1);
return ind;
and you should be all right.
You can use accomplish by keep tracking the index of each element to add it back to the result array
static class BST {
private class Node {
private Integer key;
private Node left, right;
private int index;
public Node(Integer key, int index) {
this.key = key;
this.index = index;
}
}
private Node root;
private int size = 0;
public void put(int[] arr) {
if (size >= arr.length)
return;
root = put(root, arr[size], size);
size++;
put(arr);
}
private Node put(Node node, int key, int index) {
if (node == null)
return new Node(key, index);
int cmp = Integer.valueOf(key).compareTo(node.key);
if (cmp < 0)
node.left = put(node.left, key, index);
else if (cmp > 0)
node.right = put(node.right, key, index);
else
node.key = key;
return node;
}
public int size() {
return size;
}
public int[] keys() {
int[] result = new int[size];
get(root, result, 0);
return result;
}
public void get(Node node, int[] result, int i) {
if (i >= result.length || node == null)
return;
result[node.index] = node.key;
get(node.left, result, ++i);
get(node.right, result, ++i);
}
}
, main
public static void main(String[] args) {
BST bst = new BST();
bst.put(new int[] { 10, 20, 5, 40, 1, 60, -10, 0 });
for (int num : bst.keys()) {
System.out.print(num + " ");
}
}
, output
10 20 5 40 1 60
Related
i am a cse student who takes data structures course. Trying to implement binary search algorithm to my SinglyLinkedList class, somehow i've failed. Could you check it what's wrong please ?
The related method;
I've debugged and it just enters the loops this side: else if(temp.getElement() > target)
public int binarySearchLinkedList(SinglyLinkedList<E> list, E target) {
int left = 0;
int right = list.getSize();
while (left <= right) {
int mid = (left + right) / 2;
Node<E> temp = head;
for (int i = 0; i < mid - 1; i++) {
temp = temp.next;
}
if (temp.getElement() instanceof Number && target instanceof Number) {
if (Integer.parseInt(temp.getElement().toString()) == Integer.parseInt(target.toString())) {
return mid;
} else if (Integer.parseInt(temp.getElement().toString()) > Integer.parseInt(target.toString())) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
All class for better understanding;
public class SinglyLinkedList<E> {
private static class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
element = e;
next = n;
}
private E getElement() {
return element;
}
private Node<E> getNext() {
return next;
}
private void setNext(Node<E> n) {
next = n;
}
}
private Node<E> head;
private Node<E> tail;
private int size;
public SinglyLinkedList() {
};
public int getSize() {
return size;
}
public void append(E e) {
if (head == null) {
head = new Node<E>(e, null);
tail = head;
size++;
return;
}
Node<E> temp = head;
while (temp != tail) {
temp = temp.next;
}
temp.setNext(tail = new Node<E>(e, null));
size++;
return;
}
public int binarySearchLinkedList(SinglyLinkedList<E> list, E target) {
int left = 0;
int right = list.getSize();
while (left <= right) {
int mid = (left + right) / 2;
Node<E> temp = head;
for (int i = 0; i < mid - 1; i++) {
temp = temp.next;
}
if (temp.getElement() instanceof Number && target instanceof Number) {
if (Integer.parseInt(temp.getElement().toString()) == Integer.parseInt(target.toString())) {
return mid;
} else if (Integer.parseInt(temp.getElement().toString()) > Integer.parseInt(target.toString())) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
public String toString() {
StringBuilder sb = new StringBuilder();
Node<E> temp = head;
while (temp != tail) {
sb.append(temp.getElement()).append(", ");
temp = temp.next;
if (temp == tail) {
sb.append(temp.getElement());
}
}
return sb.toString();
}
}
And the main method;
public static void main(String[] args) {
SinglyLinkedList<Integer> list = new SinglyLinkedList<>();
list.append(10);
list.append(20);
list.append(30);
list.append(40);
list.append(50);
list.append(60);
list.append(70);
list.append(80);
list.append(90);
list.append(100);
System.out.println(list);
System.out.println(list.binarySearchLinkedList(list, 30));
}
It returns;
10, 20, 30, 40, 50, 60, 70, 80, 90, 100
-1
I'm guessing this line is the biggest issue:
for (int i = 0; i < mid - 1; i++) {
Consider what happens if mid is 1. The loop won't execute, because it is not the case that 0 < 1-1. So the inspected node won't be the one you think it is. The actual node at index mid will never be inspected. So the outer loop will eventually exit, never having found the target. Presumably your method ends with return -1;.
Other issues include:
You're initializing right to an exclusive value, but treat it as inclusive elsewhere. Consider using int right = list.getSize() - 1;
You've declared a generic method, but implemented it only for Integer. One way around this would be to limit the generic type to one that supports Comparable - e.g., E extends Comparable<E>.
You're implementing a binary search in a linked list. In a linked list, linear search would be simpler and no less efficient. Or you could use a data structure that supports constant-time access by index, such as an array or ArrayList.
In my preious version of random to generate some value to array of node, it will be export the number of nodes and show the result after using BST. Then, my question is after I added scanner to input value by manually, it can't export the nodes with postorder now.
Before :
Inserting 9 nodes:
80 65 74 90 32 30 57 31 41
BST - size: 9 height: 4
30 31 32 41 57 65 74 80 90
After added insert :
Enter the number of the data: 5
Enter the values:
4
36
42
12
34
Inserted: [4, 36, 42, 12, 34]
It used postorder.
BinarySearchTree - size: 1 height: 0
trees.BSTree#30dae81
5
I expect:
Enter the number of the data: 5
Enter the values:
4
36
42
12
34
Inserted: [4, 36, 42, 12, 34]
It used postorder.
BinarySearchTree - size: $sizevalue height: $heightvalue
[4, 12, 34, 36, 42]
May I know did I need to change the tree and node?
I think you have a typo:
replace tree.insert(input); with:
for (int i = 0; i < data.length; i++) {
data[i] = sc.nextInt();
tree.insert(data[i]);
}
P.S. Preorder traversal will not give you expected output: sorted list. Tree Traversals (Inorder, Preorder and Postorder)
public final class BinarySearchTree {
private Node root;
private int size;
public void add(int val) {
root = add(root, new Node(val));
size++;
}
private static Node add(Node parent, Node node) {
if (parent == null)
return node;
if (node.val < parent.val)
parent.left = add(parent.left, node);
else
parent.right = add(parent.right, node);
return parent;
}
public boolean isEmpty() {
return size == 0;
}
public boolean find(int val) {
return dfsFind(root, val);
}
private static boolean dfsFind(Node node, int val) {
if (node == null)
return false;
if (node.val == val)
return true;
return dfsFind(node.left, val) || dfsFind(node.right, val);
}
public int[] getTraversals(Traversals traversals) {
int[] arr = new int[size];
traversals.print(root, arr, 0);
return arr;
}
public int size() {
return size;
}
public int height() {
return dfsHeight(root, 1);
}
private static int dfsHeight(Node node, int depth) {
if (node == null)
return depth - 1;
return Math.max(dfsHeight(node.left, depth + 1), dfsHeight(node.right, depth + 1));
}
public enum Traversals {
INORDER {
#Override
protected int print(Node node, int[] arr, int i) {
if (node != null) {
i = print(node.left, arr, i);
arr[i++] = node.val;
i = print(node.right, arr, i);
}
return i;
}
},
PREORDER {
#Override
int print(Node node, int[] arr, int i) {
if (node != null) {
arr[i++] = node.val;
i = print(node.left, arr, i);
i = print(node.right, arr, i);
}
return i;
}
},
POSTORDER {
#Override
int print(Node node, int[] arr, int i) {
if (node != null) {
i = print(node.left, arr, i);
i = print(node.right, arr, i);
arr[i++] = node.val;
}
return i;
}
};
abstract int print(Node node, int[] arr, int i);
}
private static final class Node {
private final int val;
private Node left;
private Node right;
public Node(int val) {
this.val = val;
left = right = null;
}
#Override
public String toString() {
return String.valueOf(val);
}
}
}
Demo:
Scanner scan = new Scanner(System.in);
System.out.print("Enter the number of the data: ");
int total = scan.nextInt();
int[] data = new int[total];
BinarySearchTree tree = new BinarySearchTree();
System.out.println("Enter the values: ");
for (int i = 0; i < data.length; i++) {
System.out.format("%d: ", i);
data[i] = scan.nextInt();
tree.add(data[i]);
}
System.out.print("Inserted: ");
System.out.println(Arrays.toString(data));
System.out.println("BinarySearchTree - size: " + tree.size() + " height: " + tree.height());
System.out.println("Inorder: " + Arrays.toString(tree.getTraversals(BinarySearchTree.Traversals.INORDER)));
System.out.println("Preorder: " + Arrays.toString(tree.getTraversals(BinarySearchTree.Traversals.PREORDER)));
System.out.println("Postorder: " + Arrays.toString(tree.getTraversals(BinarySearchTree.Traversals.POSTORDER)));
Output:
Enter the number of the data: 5
Enter the values:
0: 4
1: 36
2: 42
3: 12
4: 34
Inserted: [4, 36, 42, 12, 34]
BinarySearchTree - size: 5 height: 4
Inorder: [4, 12, 34, 36, 42]
Preorder: [4, 36, 12, 34, 42]
Postorder: [34, 12, 42, 36, 4]
to print the values of data either you need to iterate through the values using a for loop and print or you need to use Arrays class:
System.out.print(Arrays.toString(data) + " ");
I am solving the problem https://leetcode.com/problems/path-sum-iii/
I'll also briefly mention it here:
Find the number of paths in a Binary tree whose sum = sum. The path does not necessarily have to begin (end) at the root (leaf). As long as the path goes downward it should be considered as a valid path.
Here is my solution:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int pathSum(TreeNode root, int sum) {
int path = 0;
if(root.val == sum)
return 1;
else if(root.left == null && root.right == null)
return 0;
if(root.left != null){
path += pathSum(root.left, sum - root.val);
path += pathSum(root.left, sum);
}
if(root.right != null){
path += pathSum(root.right, sum - root.val);
path += pathSum(root.right, sum);
}
return path;
}
}
The answer as per their system is 3, but I am getting the answer as 4 for the following input:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ \ \
3 2 11
/ \ \
3 -2 1
Return 3. The paths that sum to 8 are:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
I have spent hours trying to reason why my code wold not work, but I cannot figure out the problem.
Sorry for a naive question :( But this is killing me!
I'm not sure what's wrong in your solution, but I don't think it's correct. For one thing, if your root was 8 you would immediately return and count only the root as solution. This is how I would do it:
import java.util.ArrayList;
public class Solution {
public static int pathSum(TreeNode root, int sum) {
return pathSum(root, sum, 0, new ArrayList<Integer>());
}
public static int pathSum(TreeNode root, int sum, int count, ArrayList<Integer> arr) {
arr.add(root.val);
int acc = 0;
for (int i=arr.size()-1; i>=0; i--) {
acc += arr.get(i);
if (acc == sum)
count++;
}
if(root.left != null)
count = pathSum(root.left, sum, count, arr);
if(root.right != null)
count = pathSum(root.right, sum, count, arr);
arr.remove(arr.size()-1);
return count;
}
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int v) {
this.val = v;
}
}
public static void main(String[] args) {
TreeNode root = new TreeNode(10);
root.left = new TreeNode(5);
root.right = new TreeNode(-3);
root.left.left = new TreeNode(3);
root.left.right = new TreeNode(2);
root.right.right = new TreeNode(11);
root.left.left.left = new TreeNode(3);
root.left.left.right = new TreeNode(-2);
root.left.right.right = new TreeNode(1);
System.out.println(pathSum(root, 8));
}
}
The idea is to populate an aarray with the value along the path as you traverse the tree recursively, making sure you remove elements as you return. When you visit a node, you have to consider all the sums from that node to any node on the path to the root. Any of them can add up to your reference value. This implementation is O(nlogn), as you traverse n nodes, and for each you traverse an array of len up to log(n).
your code cant satisfy this constraint:
these nodes should be continuous.
e.g the root(value 10) of this tree and the leaf(value -2) of this tree, the sum of them is equals 8. but it dont satisfy continous, so It cant count.
Unfortunately, your code cant filter this case.
an alternative Solution:
public class Solution {
public int pathSum(TreeNode root, int sum) {
int path = traverse(root,sum);
return path;
}
public int traverse(TreeNode root, int sum){
int path = 0;
if(root==null){
return 0;
}
else{
path += calcu(root,sum);
path += traverse(root.left,sum);
path += traverse(root.right,sum);
return path;
}
}
private int calcu(TreeNode root, int sum) {
if(root==null){
return 0;
}
else if(root.val==sum){
return 1 + calcu(root.left,sum-root.val)+calcu(root.right,sum-root.val);
}
else{
return calcu(root.left,sum-root.val)+calcu(root.right,sum-root.val);
}
}
}
explanation: traverse this tree and make every treeNode as root node, find target path under the premise continous.
the problem with your solution is that you do not start from an initial sum, if you are in a new inner path.
so you should keep track of both the accomulated sum and the original sum as well when you move inner path.
find below a modified copy of your algorithm.
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
boolean visitedAsRoot = false;
TreeNode(int x) {
val = x;
}
}
public static int pathSum(TreeNode root, int accomulate, int sum) {
int path = 0;
if (root.val == accomulate)
return 1;
else if (root.left == null && root.right == null)
return 0;
if (root.left != null) {
path += pathSum(root.left, accomulate - root.val, sum);
if (!root.left.visitedAsRoot) {
root.left.visitedAsRoot = true;
path += pathSum(root.left, sum, sum);
}
}
if (root.right != null) {
path += pathSum(root.right, accomulate - root.val, sum);
if (!root.right.visitedAsRoot) {
root.right.visitedAsRoot = true;
path += pathSum(root.right, sum, sum);
}
}
return path;
}
public static void main(String args[]) {
TreeNode t1 = new TreeNode(3);
TreeNode t2 = new TreeNode(-2);
TreeNode t3 = new TreeNode(1);
TreeNode t4 = new TreeNode(3);
TreeNode t5 = new TreeNode(2);
TreeNode t6 = new TreeNode(11);
TreeNode t7 = new TreeNode(5);
TreeNode t8 = new TreeNode(-3);
TreeNode t9 = new TreeNode(10);
t4.left = t1;
t4.right = t2;
t5.right = t3;
t7.left = t4;
t7.right = t5;
t8.right = t6;
t9.left = t7;
t9.right = t8;
System.out.println(pathSum(t9, 8, 8));
}
The problem with your solution is that it is also counting 10 - 2 = 8. where 10 is the topmost root node and -2 is a bottom leaf. It ignores all the path in between.
I managed to solve it with a tamperedSum boolean.
public static int pathSum(TreeNode root, int sum, boolean tamperedSum)
{
int path = 0;
if(root.val == sum)
path = 1;
if(root.left == null && root.right == null)
return path;
if(root.left != null){
path += pathSum(root.left, sum - root.val, true);
if (!tamperedSum)
path += pathSum(root.left, sum, false);
}
if(root.right != null){
path += pathSum(root.right, sum - root.val, true);
if (!tamperedSum)
path += pathSum(root.right, sum, false);
}
return path;
}
The tamperedSum boolean is set to true when we have deducted values (of nodes) from the original sum which in this case is 8.
We would invoke it as:
pathSum(root, sum, false)
The idea is that if the sum has been tampered i.e a node value on the path has already been deducted, we are no longer allowed to pass it as-is to the branch below the node.
So, we set tamperedSum to true whenever we deduct the node value from the sum as: sum - root.value. After that, all nodes below it are not allowed to pass through the sum without deducting their node value from it.
I'm struggling to get my desired output below. This is what I have done so far, and I think I'm close to being done.
import java.util.Scanner;
public class sortedArrayBST {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
try {
if (n <= 0) {
input.close();
}
int m = input.nextInt();
if (m <= 0) {
input.close();
}
int[] s = new int[n];
int[] w = new int[m];
for (int i = 0; i < n; i++) {
s[i] = input.nextInt();
}
for (int i = 0; i < m; i++) {
w[i] = input.nextInt();
}
} catch (IllegalStateException e) {
}
}
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode parent;
TreeNode(int x) {
val = x;
}
}
public static TreeNode sortedArrayToBST(int[] num) {
if (num == null || num.length == 0)
return null;
int start = 0, end = num.length - 1;
TreeNode root = buildTree(num, start, end);
return root;
}
public static TreeNode buildTree(int[] num, int start, int end) {
if (start > end) {
return null;
}
int mid = start + (end - start) / 2;
TreeNode node = new TreeNode(num[mid]);
node.left = buildTree(num, start, mid - 1);
node.right = buildTree(num, mid + 1, end);
return node;
}
}
I have to take user input such as:
4 // denotes number of elements in array S, variable n.
2 // number of elements in array W, variable m.
0 // 0, 25, 33, 77 are in S.
25
33
77
19 // 19 and 40 are in W.
40
Those numbers represent the sentence positions, so the ends of each sentence.
The output is
2 // 2 words of interest found, this value is always the same as W above
1 25 // start of the sentence with 1st occurrence of word of interest (end of previous sentence + 1) and end of the sentence (aka ".")
34 77 // so the previous sentence before this ended at position 33, so the next sentence started at 34, and it ends at 77.
IDK how to get this using a sorted array to a BST.
If I understand you correctly, I think what you're looking for, is a way to traverse the bst you constructed to print the output in the given format.
If that is the case, you can do an inorder traversal of the tree to achieve that.(Although, having a sorted array, constructing a bst out of it and then printing the bst in a sorted order is kind of an overkill don't you think?)
static boolean flag = false;
public static void inorderTraverse(TreeNode root){
if(root == null) return;
inorderTraverse(root.left);
if(flag){
System.out.print(root.val);
System.out.print("\n");
flag = false;
}
else{
flag = true;
System.out.print(root.val + 1 + " ");
}
inorderTraverse(root.right);
}
Finding the width of binary tree.
In my code for each leave i create a entry in a hash map and keep updating it when i found a node at leave i.Finally i will iterate the hashmap to find max width.But how can i do it without using any classleel/global varaiables?
Map<Integer,Integer> mp = new HashMap<Integer,Integer>();
void width(Node node,int level){
if(node==null)
return;
if(mp.containsKey(level)){
int count = mp.get(level);
mp.put(level, count+1);
}else{
mp.put(level, 1);
}
width(node.left, level+1);
width(node.right, level+1);
}
Just create the HashMap inside the method, then move all the work into an auxillary method, like this:
void width(Node node,int level){
Map<Integer,Integer> mp = new HashMap<Integer,Integer>();
widthImpl(mp, node, level);
// find maximum
}
private void widthImpl(Map<Integer,Integer> mp, Node node, int level) {
if(node==null)
return;
if(mp.containsKey(level)){
int count = mp.get(level);
mp.put(level, count+1);
}else{
mp.put(level, 1);
}
widthImpl(mp, node.left, level+1);
widthImpl(mp, node.right, level+1);
}
You don't need to keep track of the number of nodes per level.
Define the horizontal position of each node as the number of right children minus the number of left children that were traversed from the root to the node. The width will then be the maximum horizontal position minus the minimum horizontal position. The min/max positions could be passed around a recursive traversal in an array of two components.
Here's a code example of what I mean:
int getWidth(Node node) {
// current[0] is the number of left children traversed of the current path
// current[1] is the number of right children traversed of the current path
int[] current = { 0, 0 };
// extremes[0] is the minimum horizontal position
// extremes[1] is the maximum horizontal position
int[] extremes = { 0, 0 };
computeExtremes(node, current, extremes);
return (extremes[1] - extremes[0]);
}
void computeExtremes(Node node, int[] current, int[] extremes) {
if (node == null) { return; }
int position = current[1] - current[0];
if (extremes[0] > position) {
extremes[0] = position;
}
if (extremes[1] < position) {
extremes[1] = position;
}
current[0]++;
computeExtremes(node.left, current, extremes);
current[0]--;
current[1]++;
computeExtremes(node.right, current, extremes);
current[1]--;
}
If I understand it correctly you want to do something like this?
public Map<Integer,Integer> width( Node node ) {
Map<Integer,Integer> mp = new HashMap<Integer,Integer>();
width( node, 1, mp );
return mp;
}
private void width( Node node, int level, Map<Integer,Integer> mp ) {
if(node==null)
return;
if(mp.containsKey(level)){
int count = mp.get(level);
mp.put(level, count+1);
}else{
mp.put(level, 1);
}
width(node.left, level+1);
width(node.right, level+1);
}
This uses #nathan's algo, but passes by value.
Pair<int, int> extremes(Node node, int x, int y) {
if (node == null) return makePair(x,y);
Pair p1 = extremes(node.left, x-1, y);
Pair p2 = extremes(node.right, x, y+1);
return makePair(min(p1.x, p2.x), max(p1.y, p2.y))
}
See https://www.geeksforgeeks.org/maximum-width-of-a-binary-tree/
Use recursive with hash table
int getWidth(struct node* root, int level)
{
if(root == NULL)
return 0;
if(level == 1)
return 1;
else if (level > 1)
return getWidth(root->left, level-1) +
getWidth(root->right, level-1);
}
Use queue to dequeue parent and replace with children nodes
static int maxwidth(node root)
{
// Base case
if (root == null)
return 0;
// Initialize result
int maxwidth = 0;
// Do Level order traversal keeping
// track of number of nodes at every level
Queue<node> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty())
{
// Get the size of queue when the level order
// traversal for one level finishes
int count = q.size();
// Update the maximum node count value
maxwidth = Math.max(maxwidth, count);
// Iterate for all the nodes in
// the queue currently
while (count-- > 0)
{
// Dequeue an node from queue
node temp = q.remove();
// Enqueue left and right children
// of dequeued node
if (temp.left != null)
{
q.add(temp.left);
}
if (temp.right != null)
{
q.add(temp.right);
}
}
}
return maxwidth;
}
Something a little different:
int[] width(Node node){
if(node==null) {
return new int[]{};
}
int[] la = width(node.left);
int[] ra = width(node.right);
return merge(1, la, ra);
}
private int[] merge(int n0, int[] la, int[] ra) {
int maxLen = Math.max(la.length, ra.length);
int[] result = new int[maxLen+1];
result[0] = n0;
for (int i = 0; i < maxLen; ++i) {
result[i+1] = i >= la.length
? ra[i] : i >= ra.length
? la[i] : la[i] + ra[i];
}
return result;
}