Binary Trees are a class of tree data structures, with the following property: Each node may have a maximum of two children.
Binary Trees by themselves are typically not very useful. By applying additional constraints on top of them, they can be given useful properties. Some examples of binary trees are:
- Binary Search Trees
- Heaps
- Treaps
Problems:
- https://www.hackerrank.com/challenges/tree-preorder-traversal
- https://www.hackerrank.com/challenges/tree-postorder-traversal
- https://www.hackerrank.com/challenges/tree-inorder-traversal
- https://www.hackerrank.com/challenges/tree-height-of-a-binary-tree
- https://www.hackerrank.com/challenges/binary-search-tree-lowest-common-ancestor
A Binary Search Tree (a.k.a BST) is a type of Binary Tree, which has the following constraints added to it:
- The left subtree of the root node MUST have values less than the root node's value.
- The right subtree of the root node MUST have values greater than the root node's value.
- The left and right subtrees must be valid binary search trees.
A binary search tree gives you O(log(n)) access to any element, similar to using binary search in a sorted array.
Maps are known by various names in different contexts/languages; dictionaries, associative arrays, symbol table, etc. It is simply a collection of key-value pairs.
Maps are not part of the Iterable-Collection hierarchy, but they are still part of the framework.
A Map is internally implemented as an array of buckets. Each buckets is in itself a linked list (though this detail can change for the sake of efficiency, e.g. a bst instead of a linked list).
Each key-value pair in the bucket is stored as an Entry
. The entry class looks something like this:
private static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
final int hash;
V value;
Entry<K,V> next;
}
You can clearly make out the linked list nature of the Entry class because of the Entry<K,V> next
field.
There are two main operations that you typically perform on a Map:
-
put(key, value)
When you call theput
method, the following steps occur:- The hash of the key is calculated using the
hashCode()
method. - An index
i
is derived from the resulting hash. - An instance of the
Entry
class (e) is created, with the relevant fields. - If there is no entry at the array location
i
, the instance e is set at the location. - If there is an entry at the array location
i
, then:- If the key passed to the put method as an argument is
equal
to the key of the existing entry, then the value is updated, and the old value is returned. - If the key passed to the put method as an argument is not
equal
to the key of the existing entry, then the instance e is appended to the linked list.
- If the key passed to the put method as an argument is
- The hash of the key is calculated using the
-
get(key)
When you call theget
method, the following steps occur:- The hash of the key is calculated using the
hashCode()
method. - An index
i
is derived from the resulting hash. - A linear search for the key is conducted in the linked list at the location
i
, withequals()
being used to determine if the element is found or not. - If no element exists in the Map with this key, null is returned.
- The hash of the key is calculated using the
A simple visualization of the internal structure of the HashMap is:
Sample usage:
// A map from name to house
HashMap<String, String> houseMap = new HashMap<>();
houseMap.put("jaime", "lannister");
houseMap.put("robert", "baratheon");
houseMap.put("theon", "greyjoy");
houseMap.put("bran", "stark");
houseMap.put("ned", "stark"); // RIP
System.out.println(houseMap.get("theon")); // greyjoy
System.out.println(houseMap.get("thoros")); // null
As usual, one of the best places to understand Maps is the JavaDocs
- https://www.hackerrank.com/challenges/tree-top-view
- https://www.hackerrank.com/challenges/binary-search-tree-insertion
- https://www.hackerrank.com/challenges/is-binary-search-tree
- https://www.hackerrank.com/challenges/phone-book
- https://leetcode.com/problems/maximum-depth-of-binary-tree
- https://leetcode.com/problems/invert-binary-tree
- https://leetcode.com/problems/find-largest-value-in-each-tree-row
- https://leetcode.com/problems/merge-two-binary-trees
- https://leetcode.com/problems/average-of-levels-in-binary-tree
- https://leetcode.com/problems/maximum-binary-tree
- https://leetcode.com/problems/trim-a-binary-search-tree
- https://leetcode.com/problems/binary-tree-pruning
- https://leetcode.com/problems/sort-characters-by-frequency
- https://leetcode.com/problems/subdomain-visit-count
- https://leetcode.com/problems/most-common-word
- In the directory binarytree/problems, there is an abstract class
BinaryTree
, and a concrete classBinarySearchTree
. You need to fill in the missing methods, and write a driver program to ensure that your implementation is correct. ATreeNode
class has already been provided for you.
When reading the code, try to appreciate and understand how an abstract class is being used to provide a default implementation for some of the methods. In particular, think about these points:- Why is
BinaryTree
abstract? - Why are the methods
insert
,delete
,search
andlowestCommonAncestor
abstract?
- Why is
- Companies have several positions that an employee can be at. Employees at the same position get the same salary. Given a list of employees and their salaries, you have to determine how many positions are there at a given company. The input spec is as follows:
- The first line is a number (say N)
- N lines follow. Each line contains the name of an employee, and his salary (space separated). The salary may range from 10^5 to 10^9
- Display the number of positions at this company
- You have probably heard of the mobile application called TrueCaller. By looking at a phone number, it tells you who is calling. It works like a reverse look-up phone directory.
You have been asked to implement this application.
- The first line is a number (say N)
- N lines follow
- Each line contains a String denoting the name of a person (which may have spaces) and his/her number in a space separated manner
- Store the names and numbers
- Now start a menu-driven flow to:
- Accept a number from the user
- If the number has a name associated with it, display it.
- If it does not, inform the user that it does not exist, and give him the option to provide a name. Store the name and number.
- Display the entire reverse mapping, in the following format:
- Number1: Name
- Number2: Name
- Change a particular phone number’s owner
- Quit the program
- Accept a number from the user