Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 3

Java:

The size, isEmpty, get, set, iterator, and listIterator operations run in constant
time. The add operation runs in amortized constant time, that is, adding n elements
requires O(n) time. All of the other operations run in linear time (roughly
speaking). The constant factor is low compared to that for the LinkedList
implementation.

Operations:
Insert
Delete
Search
Navigate

List HashMap LinkedList


Insert O(n) O(1) O(1)
Delete O(n) O(1) O(1)
Search O(n) O(1) Most times O(n)
get O(1) O(1) O(n)

Linked List:
===========================================================================
For building linked list,we need to have a class called Node.
Node{
Object value; // placeholder for the value
Node nextNode; // Reference to the next node
}

In the LinkedList, we should keep track of 3 parameters


1. Node head // pointing to the 1st element in the linked list
2. Node tail // pointing to the last element in the LL
3. int length // to find the length of the linked list
==================================================================================
Binary Tree
===========================================================================
For building binary tree,we need to have a class called Node.
Node{
Object value; // placeholder for the value
Node left; // Reference to the next node
Node right; // Reference to the next node
}

In the BinaryTree class, we should keep track of 3 parameters


1. Node root // pointing to the 1st element in the Binary tree
3. int length // to find the length of the linked list
==================================================================================

Binary Tree Types:

1.Perfect Binary Tree


All nodes have either 0 or 2 nodes and all the leaf nodes exists in the lower
level.

no of nodes in the lower level = all higher level nodes+1; (since half of the
nodes are in the lower level, its efficient to search)
no of nodes in a perfect binary tree = 2^(level).
0the level -> 2^0 = 1.
1st level -> 2^1 = 2;

for binary tree its important to have it balanced, otherwise complexity would
turn to O(n)

Advantages:

1. Better than O(n), mostly log(N) for balanced tree


2. Ordered (unlike Hashmap)
3. Flexible Size
Disadvantages:
1. No O(1) operations

2. Full Binary Tree

All nodes have either 0 or 2 nodes but leaf nodes exists in different levels

Self Balancing Binary Trees:

These trees auto balance if it finds if one side is growing bigger. Java uses self
balancing trees in the hash map collision scenarios.

1. AVL Trees
https://medium.com/basecs/the-little-avl-tree-that-could-86a3cae410c7
2. Red/Black Trees:

Binary Heaps (used for Priority Queues)


=============================================
Root always higher than the children. Also we do left to right insertion, so we can
keep the order. Very useful in priority queue. For eg in Emergency Room, in loading
containers.
As we always go left to right, insertions are faster than the binary tree.

Advantages:
Better than O(n)
Priority
Flexible Size
Fast Insert

Disadvantages:

Slow Lookup O(n) time.

Trie:(Differnt type of tree)


=================================================

Its used to store the words with the letters. Best way for dictionary like things,
autocompletion, Find Number of words with a letter "A" etc.

Complexity of searching a word would be Length of the word. O(Length of word)

A B
N P A
T D P T
L
E
Graphs:
=========================================
Cyclic -> have a path in the graph back to same node
Acyclic -> No cycles
Undirected -> we can traverse both directions, no specific direction
Directed -> Only in specified direction. Though some may look cyclic they may not
have a cycle due to direction
Weighted -> We can add some weight on the edge of the graph which can use useful
for shortest path algo.

Advantages:

Best for showing relations

Dissadvantages:
Scaling is very hard

Recursion
=========================================================

How to solve recursive problems?

1. Identify base case => when the recursive call should end and return the result
2. Identify recursive case => when should we contiune making the method calls
3. Get Closer and closer to the base case and return when needed.

Recursive methods would be nested in the callStack. So the final return value from
the base value should be propagated to all the earlier calls. So for that purpose
we need to add return for recursive calls also.(Very Important)

When to use Recursion:

Every time you are using a tree or converting something into tree consider
recursion.
1. Divded into number of sub problems that are smaller instances of the same
problem.
2. Each Instance of the subprobelm is identical in nature
3. The solutions of each subproblem can be combined to solve the problem at hand

Divide and Conquer using recursion

Time Complexity:

O(2^n) ==> Be aware of this before using recursion.

=========================================================================

You might also like