Skip to content

Commit

Permalink
commit
Browse files Browse the repository at this point in the history
  • Loading branch information
abhishekghoshh committed Jan 6, 2025
1 parent e396f0e commit 6deaa07
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@

/*
* Problem link :
* https://leetcode.com/problems/validate-binary-search-tree/
* https://leetcode.com/problems/validate-binary-search-tree/description/
* https://neetcode.io/problems/valid-binary-search-tree
* https://www.geeksforgeeks.org/problems/check-for-bst/1
* https://www.naukri.com/code360/problems/check-bst_5975
*
* Solution link :
* https://www.youtube.com/watch?v=f-sj7I5oXEI&list=PLgUwDviBIf0q8Hkd7bK2Bpryj2xVJk8Vk&index=47
* https://www.youtube.com/watch?v=s6ATEkipzow
*
* https://takeuforward.org/binary-search-tree/check-if-a-tree-is-a-binary-search-tree-or-binary-tree/
* https://neetcode.io/solutions/validate-binary-search-tree
*/
public class CheckIfTreeIsBinarySearchTree {

Expand All @@ -32,11 +35,10 @@ private static void type1() {
private static boolean isValidBst(TNode root, long min, long max) {
// if the root is null, then we do not need to check
if (null == root) return true;
// if the root is lesser equal to min or higher equal to max,
// then it broke the condition
// if the root is lesser equal to min or higher equal to max, then it broke the condition
if (root.data <= min || root.data >= max) return false;
// for the left side will change higher boundary as left will be lesser
// for the right side, we will change the lower boundary
// now for the left subtree root is the upper limit
// for the right subtree, root is the lower limit
return isValidBst(root.left, min, root.data)
&& isValidBst(root.right, root.data, max);
}
Expand Down
34 changes: 19 additions & 15 deletions src/com/problems/binarysearchtree/DeleteNodeInBinarySearchTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

/*
* Problem link :
* https://leetcode.com/problems/delete-node-in-a-bst/
* https://practice.geeksforgeeks.org/problems/delete-a-node-from-bst/1
* https://www.codingninjas.com/studio/problems/delete-node-in-bst_920381
* https://leetcode.com/problems/delete-node-in-a-bst/description/
* https://www.geeksforgeeks.org/problems/delete-a-node-from-bst/1
* https://www.naukri.com/code360/problems/delete-node-in-bst_920381
*
* Solution link :
* https://www.youtube.com/watch?v=kouxiP_H5WE&list=PLgUwDviBIf0q8Hkd7bK2Bpryj2xVJk8Vk&index=45
* https://www.youtube.com/watch?v=LFzAoJJt92M
*
* https://takeuforward.org/binary-search-tree/delete-a-node-in-binary-search-tree/
* https://neetcode.io/solutions/delete-node-in-a-bst
*/
public class DeleteNodeInBinarySearchTree {

Expand All @@ -37,21 +39,23 @@ public static TNode deleteNode2(TNode root, int target) {
// if the current root is the target, then we will delete the node
if (root.data == target) return deleteNode(root);
// we are also keeping track of the parent node
TNode curr = root, prev = null;
// we need the previous node because
// we need to know that current node is in which side
TNode node = root, parent = null;
// we need the parent node as we need to know that current node is in which side
// because we need to assign a node after deleting the target node
while (null != curr) {
if (target == curr.data) {
if (prev.left == curr) prev.left = deleteNode(curr);
else prev.right = deleteNode(curr);
while (null != node) {
// if the current node is the target node then we will use the parent node
if (target == node.data) {
if (parent.left == node)
parent.left = deleteNode(node);
else parent.right = deleteNode(node);
return root;
} else if (target < curr.data) {
prev = curr;
curr = curr.left;
}
// going to the left or right based on where target may reside
parent = node;
if (target < node.data) {
node = node.left;
} else {
prev = curr;
curr = curr.right;
node = node.right;
}
}
return root;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,36 @@

/*
* Problem link :
* https://leetcode.com/problems/kth-smallest-element-in-a-bst/
* https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/
* https://neetcode.io/problems/kth-smallest-integer-in-bst
* https://www.geeksforgeeks.org/problems/find-k-th-smallest-element-in-bst/1
* https://www.naukri.com/code360/problems/kth-smallest-node-in-bst_920441
*
* https://www.geeksforgeeks.org/problems/kth-largest-element-in-bst/1
*
* Solution link :
* https://www.youtube.com/watch?v=9TJYWh0adfk&list=PLgUwDviBIf0q8Hkd7bK2Bpryj2xVJk8Vk&index=46
* https://www.youtube.com/watch?v=5LUXSvjmGCw
*
* https://takeuforward.org/data-structure/kth-largest-smallest-element-in-binary-search-tree/
* https://neetcode.io/solutions/kth-smallest-element-in-a-bst
*/
public class KthSmallestLargestElementInBinaryTree {

public static void main(String[] args) {
type1();
type2();
type3();
// all the approaches are exactly same with very mild difference
type1(); // kth smallest
type2(); // kth smallest
type3(); // kth largest
type4(); // kth largest

}


// TODO kth largest
// we will visit the nodes from right to left
// then we can skip the counting operation
private static void type3() {
private static void type4() {
TNode root = TNode.makeBST(15);
int k = 6;
Data data = new Data();
Expand All @@ -52,7 +59,7 @@ private static void inOrder2(TNode root, int k, Data data) {

// TODO kth largest
// kth largest means n-k+1 th smallest
private static void type2() {
private static void type3() {
TNode root = TNode.makeBST(15);
int k = 6;
Data data = new Data();
Expand All @@ -66,6 +73,32 @@ private static int count(TNode root) {
return 1 + count(root.left) + count(root.right);
}

// similar to the previous type, but here we will use two class level variables only
private static void type2() {
TNode root = TNode.makeBST(15);
int k = 6;
kthSmallest2(k, root);
System.out.println(ans);
}

private static void kthSmallest2(int k, TNode root) {
KthSmallestLargestElementInBinaryTree.k = k;
inOrder2(root);
}

static int k = -1;
static int ans = -1;

private static void inOrder2(TNode root) {
/// if root is null or k < 0 then we will return else we will do inorder
if (null == root || k < 0) return;
inOrder2(root.left);
// we will decrement k and check if it is 0 or not
if (--k == 0) ans = root.val;
inOrder2(root.right);
}


// TODO kth smallest
// we know the inorder of bst will give us the sorted list
// we will keep a counter, and when the counter is k then we will store the value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@

/*
* Problem link :
* https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
* https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/
* https://www.naukri.com/code360/problems/construct-binary-tree-from-inorder-and-postorder-traversal_1266106
* https://www.geeksforgeeks.org/problems/tree-from-postorder-and-inorder/1
*
* Solution link :
* https://www.youtube.com/watch?v=LgLRTaEMRVc&list=PLgUwDviBIf0q8Hkd7bK2Bpryj2xVJk8Vk&index=36
* https://www.youtube.com/watch?v=vm63HuIU7kw
*
* https://takeuforward.org/data-structure/construct-binary-tree-from-inorder-and-postorder-traversal/
* https://neetcode.io/solutions/construct-binary-tree-from-inorder-and-postorder-traversal
*/
public class ConstructBinaryTreeFromInorderAndPostorder {

Expand All @@ -25,8 +27,7 @@ public static void main(String[] args) {
}


static int postOrderIndex = 0;

// todo this is same intuition as the previous type
// The intuition is if we go root then right and left,
// so we don't have to pass the post-order position variable in the recursion.
// We can just make the global postOrder Index.Every time we hit a node.
Expand All @@ -35,72 +36,89 @@ public static void main(String[] args) {
private static void type2() {
int[] postorder = {9, 15, 7, 20, 3};
int[] inorder = {9, 3, 15, 20, 7};
int n = postorder.length;
postOrderIndex = n - 1;
// we are building a map to find the inOrder index in O(1)
Map<Integer, Integer> indices = new HashMap<>();
for (int i = 0; i < n; i++) indices.put(inorder[i], i);
TNode root = makeTree2(postorder, indices, 0, n - 1);
TNode root = buildTree2(postorder, inorder);
PrintUtl.postOrder(root);
PrintUtl.inOrder(root);
}

static TNode makeTree2(int[] postorder, Map<Integer, Integer> indices,
int inorderStart, int inorderEnd) {
if (inorderStart > inorderEnd) return null;
static int pos;

private static TNode buildTree2(int[] postorder, int[] inorder) {
int n = postorder.length;
pos = n - 1;
// we are building a map to find the inOrder index in O(1)
Map<Integer, Integer> map = new HashMap<>();
// putting (item,inorder index) in a map
for (int i = 0; i < n; i++)
map.put(inorder[i], i);
// here we will no longer carry post order index
return makeTree2(0, n - 1, postorder, map);
}

static TNode makeTree2(int start, int end, int[] postorder, Map<Integer, Integer> map) {
if (start > end) return null;
// if start and end are same, then it has only one node, so we can directly return that
if (inorderStart == inorderEnd) return new TNode(postorder[postOrderIndex--]);
if (start == end) return new TNode(postorder[pos--]);
// first, we will find the root node from the post-order index
// and decrement the post order index for the next right subtree
int rootNode = postorder[postOrderIndex--];
TNode root = new TNode(rootNode);
int inorderRootPos = indices.get(rootNode);
int root = postorder[pos--];
int rootI = map.get(root);
// for the post-order we will first go to right child first then the left child
// because the post-order sequence is left <- right <- root
root.right = makeTree2(postorder, indices, inorderRootPos + 1, inorderEnd);
root.left = makeTree2(postorder, indices, inorderStart, inorderRootPos - 1);
return root;
TNode right = makeTree2(rootI + 1, end, postorder, map);
TNode left = makeTree2(start, rootI - 1, postorder, map);
return new TNode(root, left, right);
}

// recursively
// postorder and inorder consist of unique values.
// todo we know that postorder traversal is like => left - right - root
// we know one thing that we can get root from postOrder in O(1) as it is the last item in the list
// and in inorder the seq is like => left - root - right
// now we know root so we can divide the inorder list but we need inorder index of the root
// for that we can precompute (num, inorder index) in a map
// so we can make a map to find the inorder index in O(1)
// we will start from the preOrder because in preOrder we get the root node in 0th element,
// then from that node we will get the left tree size and right tree size from the inOrder
private static void type1() {
int[] postorder = { 9, 15, 7, 20, 3 };
int[] inorder = { 9, 3, 15, 20, 7 };
int n = postorder.length;
// we are building a map to find the inOrder index in O(1)
Map<Integer, Integer> indices = new HashMap<>();
for (int i = 0; i < n; i++) indices.put(inorder[i], i);
TNode root = makeTree1(postorder, indices, n - 1, 0, n - 1);
TNode root = buildTree1(postorder, inorder);
PrintUtl.postOrder(root);
PrintUtl.inOrder(root);
}

private static TNode makeTree1(int[] postOrder, Map<Integer, Integer> indices,
int postorderPos, int inorderStart, int inorderEnd) {
if (inorderStart > inorderEnd) return null;
private static TNode buildTree1(int[] postorder, int[] inorder) {
int n = postorder.length;
// we are building a map to find the inOrder index in O(1)
Map<Integer, Integer> map = new HashMap<>();
// putting (item,inorder index) in a map
for (int i = 0; i < n; i++)
map.put(inorder[i], i);
// we will start with inorder start and end index, and we will start from the postorder last index
return makeTree1(0, n - 1, n - 1, postorder, map);
}

private static TNode makeTree1(int start, int end, int pos, int[] postOrder, Map<Integer, Integer> map) {
if (start > end) return null;
// if start and end are same, then it has only one node, so we can directly return that
if (inorderStart == inorderEnd) return new TNode(postOrder[postorderPos]);
if (start == end) return new TNode(postOrder[pos]);
// finding the root node value
int rootNode = postOrder[postorderPos];
int root = postOrder[pos];
// from the map we are getting the node's position in the inorder traversal
int inorderIndex = indices.get(rootNode);
// we need at least one child node count,
int rightCount = inorderEnd - inorderIndex;
int rootI = map.get(root);
// again, we will recursively construct it's left and right child.
// here we will create the right subtree first.
// for the right tree postorderPos root index will be (current postOrder root index + 1)
// for the right subtree inorder start will be (current inorder root index + 1)
// for the right subtree inorder end will be the same inorder end
TNode right = makeTree1(postOrder, indices, postorderPos - 1, inorderIndex + 1, inorderEnd);
TNode right = makeTree1(rootI + 1, end, pos - 1, postOrder, map);
// we have the right tree count, so we can easily construct the left tree recursion
// postOrder root will be current postOrder root position - right subtree count - 1
// as in the post-order the sequence will be like left <- right <- root
TNode left = makeTree1(postOrder, indices, postorderPos - rightCount - 1, inorderStart, inorderIndex - 1);
return new TNode(rootNode, left, right);
int rightSubtreeNodeCount = end - rootI;
TNode left = makeTree1(start, rootI - 1, pos - rightSubtreeNodeCount - 1, postOrder, map);
return new TNode(root, left, right);
}

}
Loading

0 comments on commit 6deaa07

Please sign in to comment.