//create a new interval tree node private static ITNode newNode(Interval i){ ITNode temp = new ITNode (i, i.high, null, null); return temp; }
public int max { get; set;} //maximum high value in subtree rooted with this node public ITNode(Interval i, int m, ITNode l, ITNode r){ this.i = i; this.max = m; this.left = l; this.right = r; }
public ITNode(Interval i){ this.i = i; this.left = null; this.right = null; }
//use interval BST to store previous k intervals public static bool containsNearbyAlmostDuplicate(int[] arr, int k, int l){ if (arr.Length == 0) return false; Interval interval = new Interval (arr [0] - l / 2, arr [0] + l / 2); //put first element into tree ITNode root = new ITNode (interval, interval.high, null, null); for(int i=1;i<arr.Length;i++){ Interval curr = new Interval (arr [i] - l / 2, arr [i] + l / 2); if (IntervalTree.overlapSearch (root, curr)) //if overlap, return true return true; if (i >=k) { //if tree size >= k, remove the earliest element from the tree Interval toDelete = new Interval (arr [i - k] - l / 2, arr [i - k] + l / 2); IntervalTree.delete (root, toDelete); } IntervalTree.insert (root, curr); //insert current interval to the tree } return false; }
//Check if a given interval overlaps in the given interval tree public static bool overlapSearch(ITNode root, Interval i){ //base case, tree is empty if(root == null) return false; //if i overlaps with root if(doOverlap(root.i,i)) return true; //if left child of root is present and max of left child is //greater than or equal to given interval, then i may overlap //with an interval in left subtree if (root.left != null && root.left.max >= i.low) return overlapSearch (root.left, i); //Else interval can only overlap with right subtree return overlapSearch (root.right, i); }
//check if two given intervals overlap private static bool doOverlap(Interval i1, Interval i2){ if (i1.low <= i2.high && i2.low <= i1.high) return true; else return false; }
//delete the node containing the given interval from tree public static ITNode delete(ITNode root, Interval i){ //base case if (root == null) return root; //get low value of root int l = root.i.low; //if i.low is smaller than root's low value, //then it lies in the left subtree if (i.low < l) root.left = delete (root.left, i); //if i.low is greater than root's low value, //then it lies in the right subtree else if (i.low > l) root.right = delete (root.right, i); //if i.low is equal to root's low value //then root is the node to be deleted else { //if root has only one child or no child if (root.left == null) { ITNode temp = root.right; return temp; } else if (root.right == null) { ITNode temp = root.left; return temp; } //if root with two childre: get the inorder successor //which is the smallest in the right subtree else { //Node with two children: get the inorder successor ITNode temp = minValueNode (root.right); //copy inorder successor's content to this node root.i = temp.i; root.max = temp.max; //delete the inorder successor root.right = delete (root.right, temp.i); } } return root; }
//Insert a new Interval Search Tree node //this is very similar to BST Insert. The low value of interval //is used to maintain BST property public static ITNode insert(ITNode root, Interval i){ //base case: tree is empty, new node become root if (root == null) return newNode (i); //get low value of interval of root int l = root.i.low; //if i.low is smaller than root's low value, //then i goes to the left subtree if (i.low < l) root.left = insert (root.left, i); //else, i goes to the right subtree else root.right = insert (root.right, i); //update the max value of this ancestor if needed if (root.max < i.high) root.max = i.high; return root; }