Design Analysis & Algorithm
Design Analysis & Algorithm
● Definition:
An algorithm is a finite set of steps or instructions to solve a particular problem.
Each step should take finite time to execute.
Example:
Step 1: Read A
Step 2: Read B
Step 3: Sum = A + B
Step 4: Print Sum
● This is the algorithm for adding two numbers before converting it into a program (like in
C, Java, or Python).
2. Unambiguity:
Analysis of Algorithms
● Meaning:
Comparing multiple algorithms (like linear vs binary search, quick sort vs merge sort)
to see which one performs better.
Types of Analysis
1. Priori (Before Execution):
○ Independent of hardware.
[Link]
v=7dz8Iaf_weM&list=PLxCzCOWd7aiHcmS4i14bI0VrMbZTUvlTa&index=3
Definition:
Asymptotic notation is the mathematical way to represent time complexity of an algorithm.
It helps compare algorithms without executing them (prior analysis).
It shows how running time grows with input size (n).
● Purpose:
To analyze and compare algorithms efficiently using a standard mathematical form.
○ Mathematically:
f(n) ≤ c·g(n) for n ≥ k
(c and k are positive constants)
○ Example:
f(n) = 2n² + n
→ Dominant term = n²
→ f(n) = O(n²)
(Choose c = 3, n ≥ 1 to satisfy condition)
○ Mathematically:
f(n) ≥ c·g(n) for n ≥ k
○ Example:
f(n) = 2n² + n
→ f(n) = Ω(n²)
(Choose c = 2, n ≥ 0)
○ Mathematically:
c₁·g(n) ≤ f(n) ≤ c₂·g(n) for n ≥ k
○ Example:
f(n) = 2n² + n
→ f(n) = Θ(n²)
(2n² ≤ f(n) ≤ 3n²)
the k simply represents a threshold value of input size (n) beyond which the comparison
between f(n) and g(n) always holds true.
● k: the point (or smallest input size) after which the inequality stays true for all larger n.
Example
Say you have:
f(n) = 2n² + n
and you claim f(n) = O(n²)
Let’s test:
If c = 3, then
2n² + n ≤ 3n²
→ n ≤ n² → true for n ≥ 1
✅ So here c = 3 and k = 1
Simple Analogy
● Think of searching a topic in a book (linear search):
1. Recap of Notations
Notation Meaning Relation Simple Form
Big Omega (Ω) Lower bound / best case f(n) ≥ c·g(n) a≥b
Little omega (ω) Strictly greater than (no equality) f(n) > c·g(n) a>b
Example:
If f(n) = 2n²
→ Tightest upper and lower bound = n²
→ f(n) = Θ(n²), O(n²), Ω(n²)
a) Reflexive Property
● Definition: a relation that holds when f(n) compared with itself is true.
(f(n) = O(f(n)), etc.)
b) Symmetric Property
● Definition: if f(n) = g(n) then g(n) = f(n).
Only works with equality-based relations.
c) Transitive Property
● Definition: if f(n) R g(n) and g(n) R h(n) → f(n) R h(n)
3. Quick Example
If f(n) = n²
Then:
● Describes growth:
It shows how the time or space used by an algorithm increases as the input size (n)
gets larger.
● Standard comparison:
Using notations like Big O, Big Omega, and Big Theta, we can describe:
● Main goal:
To understand how performance changes as input size grows — in other words,
how scalable the algorithm is.
● In simple words:
Θ gives both upper and lower bounds — it tells us the exact rate of growth of an
algorithm’s running time.
● Rule of thumb:
To find Θ, ignore small terms and constants, because for large n, they don’t affect
growth much.
● Example:
f(n) = 3n³ + 6n² + 6000
→ Θ(n³)
(Here, n³ dominates as n becomes large; the other terms become negligible.)
Theta (Θ) Notation – In Simple Words
● Definition:
f(n) = Θ(g(n)) means f(n) is both O(g(n)) (upper bound) and Ω(g(n)) (lower bound).
● Meaning:
Θ gives a tight bound — it shows the exact growth rate of an algorithm.
The running time grows neither faster nor slower than g(n).
● Example:
3n² + 5n + 2 = Θ(n²)
→ For large n, the n² term dominates, so the algorithm grows like n².
Transpose symmetry
[Link]
Example:
If f(n) = n² and g(n) = n,
→ f(n) + g(n) = Θ(n²)
(because n² dominates n)
2. Multiplication
Example:
If f(n) = n² and g(n) = n,
→ f(n) * g(n) = Θ(n³)
In short:
Addition
When you add two functions, the bigger one dominates.
Example:
If f(n)=n² and g(n)=n, then f(n)+g(n)=Θ(n²).
Multiplication
When you multiply two functions, their growth rates multiply.
Meaning:
If one function grows no faster than a second, and the second grows no faster than a third,
then the first also grows no faster than the third.
Example:
If
● f(n) = n
● g(n) = n²
● h(n) = n³
Then:
n = O(n²) and n² = O(n³)
➡ so n = O(n³)
1. Transpose Symmetry
● Rule:
f(n) = O(g(n)) if and only if g(n) = Ω(f(n))
● Meaning:
If one function (f(n)) grows no faster than another (g(n)),
then g(n) grows at least as fast as f(n).
They describe the same relationship from opposite sides.
● Example:
If f(n) = n and g(n) = n²
→ n = O(n²)
→ n² = Ω(n)
● Meaning:
Θ shows that f(n) grows at the same rate as g(n) —
not slower and not faster.
● In simple terms:
For large inputs:
● Example:
3n² + 5n + 2 = Θ(n²)
(n² dominates; both grow similarly for large n)
● For large n, the constant (3) becomes negligible, so f(n) behaves like 5n.
● For n ≥ 10:
4n ≤ 5n + 3 ≤ 6n
✅ This satisfies the Theta condition.
3. O(log Logarithmic Time Binary Search, Divide & Conquer type problems.
n)
6. O(n log Linearithmic Time Merge Sort, Quick Sort (average case), Heap Sort.
n)
7. O(n²) Quadratic Time Bubble Sort, Insertion Sort (worst case), Selection Sort.
10. O(2ⁿ) Exponential Time Subset Sum, Travelling Salesman (Brute Force), many
DP problems before optimization.
● Sorting algorithms:
↑ ↑ ↑
⚡ Searching Algorithms
Algorithm Best Average Worst Notes
Case Case Case
🔹 Sorting Algorithms
Algorithm Best Average Worst Notes
Case Case Case
Quick Sort O(n log O(n log n) O(n²) Worst when data already sorted & first
n) element is pivot
Merge Sort O(n log O(n log n) O(n log Same for all cases
n) n)
Insertion Sort O(n) O(n²) O(n²) Best when data already sorted
Heap Sort O(n log O(n log n) O(n log Based on heap (max/min)
n) n)
🌳 Heap Operations
Operation Single For N Notes
Element Elements
🌐 Graph Algorithms
Algorithm Time Notes
Complexity
● Floyd-Warshall → O(n³)
Ans is “b”
🎯 Goal:
3. For large n, powers (like (log n)¹⁰) grow slower than n terms.
⇒ n² log n grows faster.
Divide F₂ by F₁:
→ (n¹⁰ (log n)¹⁰) / (n² log n) = n⁸ (log n)⁹
✅ Final comparison:
F₁(n) = O(F₂(n))
or
F₂(n) = Ω(F₁(n))
🧠 Question: Compare the following time complexities
Given functions:
● F₁(n) = 2ⁿ
● F₂(n) = n^(3/2)
● F₃(n) = n log n
● F₄(n) = n^(log n)
log n < √n < n < n log n < n² < n³ < ... < 2ⁿ < nⁿ
F₂(n) 16^(3/2) 64
F₃(n) 16 × log₂16 = 16 × 64
4
So:
F₃ ≈ F₂ < F₄ < F₁
Order confirmed.
💡 Quick Tip
● Use large n values to check dominance.
● For simplification:
○ n3/2=nnn^{3/2} = n \sqrt{n}n3/2=nn
○ nlognn^{\log n}nlogn grows faster than any polynomial but slower than 2n2^n2n.
Final Answer:
✅ Increasing Order → F₃, F₂, F₄, F₁
L-3.1: How Quick Sort Works | Performance of Quick Sort with Example | Divide and Conquer
🎯 Quick Sort – Gate Smashers Notes
1 What is Quick Sort?
1️⃣
○ P → moves from left to right (RHS), stops when it finds element greater than
pivot.
○ Q → moves from right to left (LHS), stops when it finds element smaller than
pivot.
5️⃣When to Swap?
Condition Action
7️⃣Example Flow
● Recurrence relation:
T(N) = 2T(N/2) + N
(N for scanning whole array each pass)
🧠 Summary
● Technique: Divide and Conquer
● The position of the pivot determines whether the partition is balanced or unbalanced.
2. Best Case
● When: Pivot divides the array equally into two parts (N/2 and N/2).
● Reason: Each partition is balanced, and the array reduces in size efficiently.
3. Average Case
● Usually close to the best case.
4. Worst Case
● When: Pivot always becomes the smallest or largest element,
so one side has N−1 elements and the other has 0 elements.
Recurrence Relation:
T(N) = T(N−1) + N
Time Complexity:
O(N²)
6. Summary
Case Pivot Position Time Complexity
1. Definition
● Merge Sort is a Divide and Conquer algorithm.
● It repeatedly divides the array into smaller parts, sorts them, and merges them back in
sorted order.
2. Key Idea
● Divide: Split the array into two halves until each sub-array has only one element.
● Conquer (Merge): Combine (merge) the sub-arrays while sorting them in ascending
order.
3. Steps (Example)
Given array:
[6, 4, 2, 1, 9, 8, 3, 5]
1. Divide Phase:
3. Merge again:
[4,6] + [1,2] → [1,2,4,6]
[8,9] + [3,5] → [3,5,8,9]
4. Final Merge:
[1,2,4,6] + [3,5,8,9] → [1,2,3,4,5,6,8,9] ✅ (Sorted array)
5. Time Complexity
● Best Case: O(n log n)
● Average Case: O(n log n)
6. Space Complexity
● Requires extra space for temporary arrays during merging.
→ O(n)
7. Summary
Phase Description Example
1. Definition
● Bubble Sort is a simple comparison-based sorting algorithm.
● It repeatedly compares adjacent elements and swaps them if they’re in the wrong
order.
2. How It Works
● Start from the first element and compare it with the next one.
● Continue comparing until the end of the array — this completes one pass.
● After each pass, the largest element moves to its correct position (end of the array).
Pass 1:
→ Compare & swap where needed → [9, 10, 6, 11, 2, 15]
(Largest element 15 moved to correct position)
Pass 2:
→ [9, 6, 10, 2, 11, 15]
(Next largest element 11 fixed)
Pass 3:
→ [6, 9, 2, 10, 11, 15]
(Third largest element 10 fixed)
4. Key Observation
After every pass:
✅ One more element is sorted (placed correctly at the end).
✅ Remaining comparisons reduce:
5. Time Complexity
● Total comparisons: (n−1) + (n−2) + (n−3) + … + 1
= n(n−1)/2 = O(n²)
● Number of swaps and comparisons are maximum in the worst case (reverse-sorted
array).
7. Summary Table
Case Description Time Complexity
🎯 Introduction
● Insertion Sort is a simple and intuitive sorting algorithm.
● Works similarly to the way we arrange cards in our hands while playing.
○ Pick the next card → place it in the correct position relative to the first.
○ For every new card, compare it with the sorted cards (on the left) and insert it
into its correct position.
Step-by-step:
2. Take next element 20 → compare with 40, since 20 < 40, insert before → [20,
40]
3. Take next element 60 → compare with 40, since 60 > 40, place after → [20, 40,
60]
4. Take next element 10 → compare with 60, 40, 20, insert before all → [10, 20,
40, 60]
5. Take next element 50 → compare with 60, insert before 60 → [10, 20, 40, 50,
60]
6. Take last element 30 → compare with 60, 50, 40, insert before 40 → [10, 20,
30, 40, 50, 60]
💻 Algorithm / Pseudocode
for j = 2 to length(A)
key = A[j]
i = j - 1
while i > 0 and A[i] > key
A[i + 1] = A[i]
i = i - 1
A[i + 1] = key
Explanation:
Explanation:
● Best Case: Elements already sorted → only one comparison each time → O(N)
● Worst Case: Elements in reverse order → each new element compared with all
previous → O(N²)
⚖️Stability
● Stable Sorting Algorithm
🌐 Online Algorithm
● Called Online Algorithm because:
In-place? Yes
Stable? Yes
Best Case Time O(N)
🧩 Advantages
● Simple and easy to implement.
⚠️Disadvantages
● Inefficient for large datasets (O(N²)).
L-3.8: Selection Sort | Time Complexity(Best, Avg & Worst) Analysis | Stable or Not | Inplace or
Not
🎯 Introduction
● Selection Sort is a simple comparison-based sorting algorithm.
● It is important for competitive exams, college, and university exams, and often asked
in interviews.
● The algorithm repeatedly selects the minimum element from the unsorted portion and
places it in the correct position of the sorted portion.
⚙️Concept
● The main idea:
In each pass, find the minimum element from the unsorted array and swap it with the
first unsorted element.
○ 20 < 40 → min = 20
○ 60 > 20 → no change
○ 10 < 20 → min = 10
○ 50 > 10 → no change
○ 30 > 10 → no change
● Swap 10 and 40
→ Array becomes [10, 20, 60, 40, 50, 30]
● Assume min = 20
○ 60 > 20
○ 40 > 20
○ 50 > 20
○ 30 > 20
● Assume min = 60
○ 40 < 60 → min = 40
○ 50 > 40
○ 30 < 40 → min = 30
● Minimum element = 30
● Swap 30 and 60
→ [10, 20, 30, 40, 50, 60]
🔹 Step 4 & 5
● The process continues:
○ 4th pass: 40 already at right place
💻 Pseudocode / Algorithm
for i = 0 to n - 2
min_index = i
for j = i + 1 to n - 1
if A[j] < A[min_index]
min_index = j
swap(A[i], A[min_index])
🔹 Number of Swaps
● Only one swap per pass, even in the worst case.
● Swaps = 0 → O(1)
● Swaps = n → O(n)
🔹 Average Case
● Comparisons ≈ n(n-1)/2 → O(n²)
● Swaps ≈ n → O(n)
🧠 Space Complexity
● Uses only a few extra variables (min, i, j).
⚖️Stability
● ❌ Selection Sort is NOT a Stable Algorithm.
🔸 Example:
5A, 2, 3, 5B, 1
● After sorting:
1, 2, 3, 5B, 5A
📋 Summary Table
Property Description
Stable Algorithm ❌ No
🌟 Advantages
● Simple and easy to implement.
● Performs fewer swaps than bubble or insertion sort.
⚠️Disadvantages
● Inefficient for large datasets due to O(n²) comparisons.
🔹 Introduction
● Counting Sort is a non-comparison-based sorting algorithm.
● Unlike Quick Sort, Merge Sort, Selection Sort, or Bubble Sort, which compare
elements, Counting Sort works by counting occurrences of elements.
🔹 Key Idea
● Counting Sort sorts elements by counting the frequency (number of occurrences) of
each distinct element in the input array.
● It works efficiently when the range (K) of input elements is not significantly greater than
the number of elements (N).
Example:
A = [2, 1, 2, 3, 1, 2, 4]
Range K = 5
3. Count Occurrences
Traverse the input array A and record how many times each element appears in C.
Example traversal:
A = [2, 1, 2, 3, 1, 2, 4]
After counting:
C = [2, 3, 1, 1, 0]
For each index i, write that number in the output array as many times as it occurred.
Output array:
Sorted = [1, 1, 2, 2, 2, 3, 4]
🔹 Visualization Example
Ste Input Count Array (Occurrences) Output
p
1 [2, 1, 2, 3, 1, 2, 4] [0, 0, 0, 0, 0] —
2 Count [2, 3, 1, 1, 0] —
occurrences
3 Construct output — [1, 1, 2, 2, 2, 3, 4]
🔹 Time Complexity
Counting Sort’s time complexity depends on:
Formula:
Time Complexity=O(N+K)\text{Time Complexity} = O(N + K)Time Complexity=O(N+K)
Explanation:
🔹 Space Complexity
Space Complexity=O(K)\text{Space Complexity} = O(K)Space Complexity=O(K)
● Because an extra array of size equal to the range (K) is used to store counts.
🔹 Advantages
✅ Works in linear time (O(N + K)) for small range values.
✅ Stable algorithm — maintains the relative order of equal elements.
✅ Very efficient when the range is small and known.
🔹 Disadvantages
❌ Range must be known in advance.
❌ Not efficient for large ranges — requires extra memory.
● Example: If one element is 20,000, then array size for counting must be
20,000.
❌ Works only for integers or discrete values (not floating-point or strings directly).
1. Collect emails: Gather a set of emails that we want to analyze for spam filtering.
2. Examine each email: Mark each email as spam or not spam based on specific
criteria.
3. Identify words: Identify keywords that help in classifying the emails as spam or
not spam.
4. Create a list of markers: Collect these keywords that serve as markers for spam
detection.
● Example:
We define a threshold for spam. If the probability of spam is greater than 50%, the email
is flagged as spam.
● Dataset Example:
We have a set of 8 emails, out of which 5 are spam and 3 are not.
Each email is labeled as spam or not spam.
● Data Summary:
○ Total emails: 8
● Action:
Count the occurrences of each word in the emails and normalize them (e.g., "send"
appears 3 times, "your" appears 4 times).
● Example:
A dictionary might contain words like:
○ "send" = 3
○ "your" = 4
Text
○ "account" = 3
○ "report" = 1
and so on for all unique words in the emails.
Objective:
In this step, we aim to calculate the probability of each word occurring in spam emails. This
helps us understand how likely it is for a given word to appear in a spam email. By calculating
these probabilities, we can later use them to assess whether an email is spam or not.
Formula:
To calculate the probability of a word given that an email is spam, we use the following formula:
● Vocabulary size:
This is the number of unique words (the different words) in your entire dataset (spam
+ not spam emails). For example, if there are 10 unique words, then the vocabulary size
is 10.
● +1 (Laplace Smoothing):
The "+1" is used to avoid a zero probability for any word that doesn't appear in the
spam emails. If a word is missing from a spam email, it would have a zero probability,
which can be problematic for calculations. Adding 1 ensures that all words, including
unseen ones, are treated fairly.
● Total words in spam emails = 18 (total of all words across all spam emails)
So, the probability of the word "send" appearing in a spam email is 0.166 or 16.6%.
● Formula:
P(Spam∣Email)=P(Spam)×P(word1∣Spam)×P(word2∣Spam)×…P(Spam|
Email) = P(Spam) \times P(\text{word1}|Spam) \times P(\text{word2}|Spam)
\times \dotsP(Spam∣Email)=P(Spam)×P(word1∣Spam)×P(word2∣Spam)×…
● Example:
P(Spam∣Email)=0.625×0.166×0.166×⋯=0.0172P(Spam|Email) = 0.625 \
times 0.166 \times 0.166 \times \dots =
0.0172P(Spam∣Email)=0.625×0.166×0.166×⋯=0.0172
This is the probability that the email is spam.
✅ Explanation:
● The product of these values gives the likelihood that the email is spam based on its
words.
● Decision:
If the calculated probability is higher than the threshold (e.g., 50%), the email is
classified as spam. If it is lower, it is classified as not spam.
SVM:
Lec-40: Support Vector Machines (SVMs) | Machine Learning
4. Create a List: Collect all such keywords (markers) that identify an email as spam or not.
The SVM (Support Vector Machine) algorithm is used to find the optimal boundary
(hyperplane) to separate these two classes—spam and not spam. It uses the words in the email
(like "free" or "gift") to distinguish between the two classes.
● Example Dataset: The dataset contains messages labeled as either "spam" or "not
spam." Each message is labeled so the algorithm can learn what spam and non-spam
emails look like.
● Sample Messages:
This dataset will be used by the model to understand which words are commonly found in spam
versus non-spam emails.
By multiplying TF and IDF, you get the TF-IDF score, which represents the importance of a
word in a document. This helps in converting emails into numeric vectors (lists of numbers) that
the machine learning model can use.
● Presence or Absence: The emails are converted into vectors based on whether they
contain the words "free" or "meeting."
○ For example, if a message contains the word "free," it gets a 1 (indicating "yes").
○ If the
○
○ message doesn’t contain the word "meeting," it gets a 0 (indicating "no").
Example:
This step turns each email into a format that SVM can use.
Important Terms
● Hyperplane:
A decision boundary that separates data points of different classes.
For example, in an email spam classification, a hyperplane might separate "spam" and
"not spam."
● Margin:
The distance between the hyperplane and the nearest data point from either class.
Goal: Maximize the margin for better separation.
● Support Vectors:
The data points closest to the hyperplane that influence its position. These points are
crucial for defining the boundary.
Example:
● f(n) = 5n + 3
○ Using constants, we can say f(n) = Θ(n), meaning f(n) grows proportionally to
n.
Types of Margins
1. Hard Margin:
Data can be perfectly separated by a hyperplane (no overlap).
2. Soft Margin:
Data can't be perfectly separated; some points might overlap or fall inside the margin.
● Non-linear Kernels (e.g., Polynomial, Radial Basis Function): Used to increase the
dimensions of the data, making it easier to separate.
Key Takeaways:
● SVM aims to maximize the margin for better classification.
● If data isn't linearly separable, SVM uses kernel functions to map data into higher
dimensions and make it separable.
In short:
SVM separates data using a hyperplane, and the goal is to maximize the margin for better
accuracy. Support vectors are crucial, and kernels help when the data isn't linearly separable.
TF-IDF Explained with Solved Example in Hindi l Natural Language Processing
1. Definition
● Greedy Algorithm (or Greedy Technique):
An algorithmic approach that selects the best local (immediate) choice at each step
with the hope of finding a global optimum.
Key Idea:
“Choose the best option available at the moment (locally optimal), expecting it will
lead to the best overall solution (globally optimal).”
2. Concept Explanation
● At each stage, the algorithm makes a choice that looks best at that moment.
● There is no guarantee that the final result will be globally optimal, but for many
problems, it gives the correct or near-optimal solution.
○ Path A: 10
○ Path B: 20
○ Path C: 5
● The Greedy algorithm will choose the path with the lowest cost (5) at this stage.
● This decision is local (based only on current data), aiming for global optimality
(minimum total cost).
4. Terminologies
a) Solution Space
● All possible options or solutions to a problem.
Example: All career options after school — Engineering, Medical, Banking, Business,
etc.
b) Feasible Solution
● Solutions that satisfy some constraints or selection criteria.
c) Optimal Solution
● The best feasible solution according to a particular goal:
○ Minimum cost
○ Maximum profit
○ Minimum risk
5. Real-Life Analogy
Career Choice Example:
● Solution Space: All possible career options.
● Optimal Solution: Chosen based on personal goals (e.g., least cost, maximum salary,
minimum risk).
Offer Example (Shopping Analogy):
● During sales, we tend to choose the store offering maximum discount (maximum profit)
regardless of quality.
7. Important Note
● Greedy algorithms do not guarantee a global optimum in every case.
● They work well only when a local optimum leads to a global optimum.
2. Greedy by Weight:
● Usage: Primarily used for optimization problems where you try to find the best solution
quickly.
● Fractional Knapsack
● Dijkstra’s Algorithm
● Kruskal’s Algorithm
● Huffman Coding
● Prim’s Algorithm
● Fast Solutions: Provides quick solutions but not always the best or optimal ones.
● No Backtracking: Once a decision is made, it’s final; the algorithm doesn’t reconsider.
● Based on Current Info: It makes choices based on available information at that time,
without considering future consequences.
Note: While greedy algorithms work well in many cases, they are not always optimal for all
problems, as shown in some examples.
3. Pick the best option at that moment, even if it’s not the best in the long term.
4. Move to the next step based on the chosen option, and continue until the problem is
solved.
Key Idea: The algorithm makes the best choice at each step without considering future
consequences. It’s a quick, but not always the most accurate, approach.
Steps:
1. Start with the highest coin denomination that’s less than or equal to the amount. The
largest coin for 39 is 10.
2. Subtract the coin value from the total amount and add it to the solution (e.g., 39 - 10 =
29).
● Non-Revisitable Choices: Once a decision is made, it’s not revisited, which makes
them less flexible.
● Limitation: The algorithm might fail if making a locally optimal choice blocks access to
a better long-term solution.
Final Thoughts: Greedy algorithms are great for quick solutions, but they might not always
lead to the best result for every problem.
Knapsack Problem – Notes
L-4.2: Knapsack Problem With Example| Greedy Techniques| Algorithm
Definition:
○ You are given a set of items, each with a profit and weight.
○ The goal is to maximize the profit by selecting a combination of items such that
their total weight does not exceed the bag's capacity.
Problem Statement:
● We are given:
○ The goal is to maximize the total profit while keeping the total weight within the
limit of 20.
Greedy Technique:
● Greedy Approach means always selecting the best immediate option, based on the
current information, without considering future consequences.
Three Approaches:
4. Greedy by Profit:
○ Example: The item with the highest profit is Object 1, with a profit of 25.
○ Example:
Algorithm Steps:
3. Select Items:
○ Add items to the knapsack starting with the highest ratio, until the bag's capacity
is filled.
Time Complexity:
● Calculating the ratio and sorting the items takes O(n log n) time.
Conclusion:
● The Greedy Algorithm is effective but may not always provide the best solution unless
both profit and weight are considered.
● Using the profit-to-weight ratio method gives the optimal solution for the knapsack
problem.
Summary:
● Knapsack Problem: Maximize profit while staying within weight limit.
● Greedy Techniques:
● Optimal Approach: Calculate Profit/Weight Ratio, sort, and select items accordingly.
Huffman Coding:
L-4.3: Huffman Coding Algorithm in Hindi with Example | Greedy Techniques(Algorithm)
L-4.4: Huffman Coding Question in Greedy Technique | Imp Question for all competitive exams
Definition:
● A spanning tree of a graph is a connected subgraph that includes all the vertices of
the original graph without any cycles.
1. Connected:
2. No Cycles:
4. V-1 edges:
○ A spanning tree will always have one fewer edge than the number of vertices,
i.e., if there are 4 vertices, the tree will have 3 edges.
Example:
○ Vertices: 1, 2, 3, 4.
● A spanning tree of this graph must include all 4 vertices and exactly 3 edges. You can
form multiple spanning trees for a single graph, depending on the way you connect the
edges.
● There can be multiple spanning trees for a single graph. For example, with 4 vertices,
you can create different spanning trees by connecting the vertices in different ways.
● For a complete graph with 4 vertices (K4), there are 16 possible spanning trees.
○ For example, for K4, N = 4, so the number of spanning trees = 4^(4-2) = 4^2 =
16.
● N^(N-2): This is used when you have a complete graph and want to calculate the
number of possible spanning trees.
○ Example for K5: For 5 vertices, 5^(5-2) = 5^3 = 125 spanning trees.
● Two popular algorithms used to find the minimum cost spanning tree are:
1. Kruskal’s Algorithm
2. Prim’s Algorithm
● These algorithms are crucial in the greedy technique and are commonly used for
finding minimum cost spanning trees.
Conclusion:
● Greedy algorithms like Kruskal’s and Prim’s are used to find the minimum cost
spanning tree.
● For complete graphs, the number of possible spanning trees can be calculated using
the formula N^(N-2).
Summary:
● A spanning tree is a connected, acyclic subgraph with all vertices and V-1 edges.
● For complete graphs, use the formula N^(N-2) to find the number of spanning trees.
● Kruskal's and Prim's algorithms are used to find the minimum cost spanning tree.
Introduction:
● Kruskal’s Algorithm is used to find the minimum cost spanning tree (MST) of a
graph.
● It is a greedy algorithm that selects the edges with the minimum weight first, ensuring
that no cycles are formed.
1. Number of vertices: The number of vertices in the spanning tree is the same as in the
original graph.
2. Number of edges: A spanning tree will always have V - 1 edges (where V is the
number of vertices).
4. Connectivity: The spanning tree should be connected, meaning all vertices should be
reachable.
2. Pick the smallest edge. Add it to the spanning tree if it doesn't form a cycle.
3. Repeat the process: Continue selecting the smallest edge that does not form a cycle
until you have V-1 edges (where V is the number of vertices in the graph).
Example:
● Start by sorting the edges in increasing order and pick the smallest edge that doesn’t
form a cycle.
● If you have edges like B-E (weight 2), A-C (weight 3), and so on, select the minimum
one and continue adding edges without forming any cycles.
● The final minimum cost spanning tree will have 6 edges (for 7 vertices), and the sum
of weights will give the minimum cost.
Important Concepts:
2. Cycle Check: Even if an edge has the minimum weight, it is not included if it forms a
cycle.
Time Complexity:
○ If using a Min-Heap, the complexity is O(E log E), where E is the number of
edges.
○ In the best case, if there are N-1 edges (where N is the number of vertices), the
time complexity is O(N log E).
○ In the worst case, you might need to check all edges, so the time complexity is
O(E log E).
Conclusion:
● Kruskal's algorithm is efficient for finding the minimum cost spanning tree in a graph.
● The algorithm is based on greedy principles: it always chooses the minimum weight
edge first and avoids cycles.
● It is simple and easy to implement, especially when the edges are already sorted.
● The time complexity is O(E log E), which can be improved using Min-Heaps for edge
sorting.
Summary:
● Kruskal's Algorithm: Used to find the minimum cost spanning tree in a graph.
● Steps: Sort edges by weight, pick the smallest edges, and avoid cycles until you have V-
1 edges.
Introduction:
● Prim’s Algorithm is used to find the minimum cost spanning tree (MST) in a
weighted, undirected graph.
● It works by adding the shortest edges to the tree in a way that the tree remains
connected and does not form cycles.
Key Concepts:
1. Spanning Tree:
○ A spanning tree includes all the vertices of the graph and has exactly V-1 edges
(where V is the number of vertices).
○ The goal is to find the spanning tree with the least total edge weight.
1. Start from any vertex: Choose any vertex as the starting point. If the starting vertex is
provided, begin from there.
2. Select the smallest edge: From the chosen vertex, pick the smallest edge (with the
least weight) that connects it to an unvisited vertex.
3. Repeat the process: Add the smallest edge from the tree to the unvisited vertices,
ensuring no cycles are formed.
4. Stop when: You have added V-1 edges (where V is the number of vertices) to the tree.
○ Check the connected edges: B-A (weight 1) and B-C (weight 6). Pick the edge
with the minimum weight (B-A).
○ From A, check the connected edges: A-D (weight 5) and A-B (already chosen).
Pick A-D (weight 5).
○ From D, check the connected edges: D-F (weight 2), D-C (weight 6), and D-B
(already chosen). Pick D-F (weight 2).
○ From F, check the connected edges: F-C (weight 3), F-D (already chosen).
Pick F-C (weight 3).
5. Continue the process: Add the remaining vertices and edges until all vertices are
included in the tree.
Key Points:
● Greedy Choice: Always pick the smallest edge that connects an unvisited vertex to the
growing spanning tree.
Time Complexity:
● The time complexity of Prim’s Algorithm is O(E log V) (where E is the number of edges
and V is the number of vertices).
○ Using Min-Heap: The algorithm can be optimized using a Min-Heap for edge
selection, making it more efficient.
Summary:
● Prim’s Algorithm is a greedy algorithm to find the minimum cost spanning tree.
● It works by starting from any vertex and adding the minimum weight edge at each step,
ensuring the tree remains connected and acyclic.
● The time complexity is O(E log V) when using efficient data structures like Min-Heaps.
Important Tips:
● Cycle Check: Always make sure that adding an edge doesn’t form a cycle.
● Greedy Property: Prim’s algorithm makes locally optimal choices at each step, aiming
for a globally optimal solution.
● The result from Prim’s will be the same as Kruskal's algorithm in terms of the
minimum spanning tree, though the approaches differ.
Introduction:
● Dijkstra's Algorithm is used to find the shortest path from a single source vertex to
all other vertices in a weighted graph.
● It is a greedy algorithm that gives the minimum cost path.
● Commonly used in network routing (e.g., Google Maps, social networking, DNA
mapping).
Key Concepts:
○ The algorithm finds the shortest path from a single source vertex to all other
vertices.
2. Greedy Approach:
○ The algorithm always selects the minimum weight edge to progress towards
the next vertex, ensuring optimal solution.
3. Relaxation:
4. Spanning Tree:
○ The final result is a shortest path spanning tree rooted at the source.
Algorithm Steps:
1. Initialization:
○ Set the distance of the source vertex to 0 and all other vertices to infinity.
2. Relaxation:
○ From the source, examine all neighboring vertices. If a shorter path is found,
update the distance.
○ Repeat this process for all vertices, ensuring that the shortest paths are always
chosen.
3. Continue:
○ Always choose the unvisited vertex with the smallest tentative distance.
2. Relax edges:
○ From 1 to 2: Distance = 7.
○ From 1 to 3: Distance = 9.
4. Repeat the process until all vertices have the shortest path known.
Key Points:
● Connected Graph: The algorithm works on connected graphs where there is a path
from the source to every other vertex.
Time Complexity:
● Using Min-Heap: O(E log V) (where E is the number of edges, and V is the number of
vertices).
Disadvantages:
● Negative Weight Edges: Dijkstra's algorithm does not work if the graph contains edges
with negative weights.
● Process: Start from vertex 1, update the shortest paths to 2, 3, 6, etc., and stop when all
vertices are visited.
Conclusion:
● Dijkstra's algorithm is ideal for finding the shortest path in a graph with non-negative
weights.
● Dijkstra's algorithm finds the shortest path from a single source vertex to all other
vertices in a graph with non-negative weights.
● It is used for single source shortest path problems and works on both directed and
undirected graphs.
● Real-life example: Google Maps, where you need to find the shortest path from a
source location to all other possible destinations.
Key Concepts:
1. Graph Representation:
2. Greedy Approach:
3. Relaxation:
○ Relaxation is the process of updating the shortest distance of a vertex. If a
shorter path is found, update the distance.
Algorithm Steps:
1. Initialize:
○ Set the distance from the source to itself as 0, and all other vertices to infinity.
2. Heap Construction:
3. Extract Minimum:
○ Extract the vertex with the minimum distance from the heap.
4. Relaxation:
○ For each neighboring vertex, update the distance if a shorter path is found.
5. Repeat:
Example:
● Graph:
○ Vertices: {1, 2, 3}
● Process:
■ From 1 to 2: 7, 1 to 3: 9.
Time Complexity:
● Initial Setup: Set the distance of all vertices to infinity – O(V), where V is the number of
vertices.
● Extract Min: Extracting the minimum value from the heap takes O(log V). This is done
for each vertex, so the total time for this operation is O(V log V).
● Relaxation: Relaxing each edge involves checking each neighbor, taking O(E log V)
time, where E is the number of edges.
● Total Complexity: O(E log V) (in general, edges are usually more than vertices, so the
complexity is based on edges).
Disadvantages:
● Negative Weights: Dijkstra’s algorithm does not work with negative weight edges.
● Efficiency: While it is efficient for graphs with non-negative weights, it may not be the
best choice for graphs with negative weights or very dense graphs.
Conclusion:
● Dijkstra's algorithm is a greedy algorithm for finding the shortest path in graphs with
non-negative weights.
● Time complexity: O(E log V), where E is the number of edges and V is the number of
vertices.
Graph Traversal
● Definition: The process of visiting and exploring a graph (or tree) for processing.
Involves two main tasks:
○ Visiting a vertex.
○ Every tree is a graph, but not every graph is a tree (graphs can have cycles,
trees cannot).
1. Breadth-First Search (BFS)
● Method: BFS explores the graph level by level, visiting all nodes at the current level
before moving to the next.
○ Queue Data Structure: FIFO (First In First Out) is used to keep track of nodes.
● Working:
○ Visit and explore all the neighbors before moving to the next level.
● Example:
● Real-Life Example: Like exploring all food stalls at a food court: you visit each stall on
the same level before moving to the next row of stalls.
○ V = number of vertices.
○ E = number of edges.
○ Stack Data Structure: LIFO (Last In First Out) is used to keep track of nodes.
● Working:
● Example:
● Real-Life Example: Like choosing a career path and sticking to it until you hit a dead
end, then backtracking to explore other options.
○ V = number of vertices.
○ E = number of edges.
3. Backtracking:
4. Graph Exploration:
○ BFS: Can be more useful when the graph is large or you need the shortest path
in an unweighted graph.
○ DFS: Often used for tasks like topological sorting or checking connectivity.
Applications:
● BFS:
● DFS:
Conclusion:
● BFS is better for level-order traversal, while DFS is better for deep explorations.
● Both algorithms are important in computer science and have many practical
applications, such as in network routing, web crawlers, and social media connections.
Introduction
○ Problems can be broken into smaller subproblems, each with an optimal solution.
○ Example: In the Fibonacci sequence, each term is the sum of the previous two
terms. This is the optimal substructure.
2. Overlapping Subproblems:
○ Example: In the Fibonacci sequence, f(2) and f(1) are computed multiple
times. DP stores the result to avoid recomputation.
○ Example: For the Fibonacci sequence, to calculate f(4), we need f(3) and
f(2). We break it down further until the base case.
○ Once a subproblem is solved, its solution is stored to avoid solving the same
problem again. This leads to overlapping subproblems.
○ Example: We store the results of f(2), f(3), etc., so that we don’t recompute
them multiple times.
○ After solving all the subproblems and storing the results, DP combines these
solutions to form the optimal solution for the original problem.
● Fibonacci Sequence: Storing the values of f(2), f(3), etc., to avoid recalculating.
● Matrix Chain Multiplication: To find the most efficient way to multiply a series of
matrices.
● 0-1 Knapsack Problem: Solving the problem of selecting items with given weights and
values to maximize profit within a weight limit.
● Traveling Salesman Problem (TSP): Finding the shortest route that visits all cities once
and returns to the origin city.
● All Pair Shortest Path: Finding the shortest paths between all pairs of nodes in a graph.
Conclusion
● Dynamic Programming solves optimization problems by breaking them down into
overlapping subproblems and storing the solutions to avoid recomputation. It guarantees
an optimal solution, unlike Greedy Algorithms, which might not always give the best
result.
Definition of TSP
● Travelling Salesman Problem (TSP) involves a salesman who must travel through
multiple cities (nodes in a graph), visiting each city once, and return to the starting city,
all while minimizing the total cost (or distance).
● Objective: Find the minimum cost to visit all cities once and return to the starting point.
○ Greedy approach selects the next nearest city at each step (locally optimal
choice).
○ Example:
■ Start from city 1, choose the nearest city (cost 10 to city 2).
■ From city 2, choose the next nearest city (cost 10 to city 4), and so on.
○ Problem with Greedy: This method doesn’t always give the optimal solution, as
it may not consider future costs effectively.
○ Brute force: Try all possible city visit combinations and calculate the total cost
for each. The one with the minimum cost is the answer.
○ Example: For 4 cities, evaluate all possible routes and select the one with the
least cost.
○ Challenges: While DP can reduce time complexity, it still cannot convert the
problem into polynomial time. TSP remains an NP-complete problem.
○ Hint for DP: Subproblems must overlap, but in TSP, subproblems are not
entirely overlapping, so DP isn't fully effective for this problem.
Time Complexity
● Brute Force: O(N!) time complexity (factorial), as it evaluates all possible permutations.
● Dynamic Programming: Reduces the time complexity but still remains exponential in
nature for TSP.
Key Insights
● TSP is NP-Complete: This means that no known polynomial-time algorithm can solve
TSP efficiently for large graphs.
● Hamiltonian Cycle: TSP is related to the Hamiltonian cycle, where you need to visit all
nodes exactly once and return to the starting node.
Conclusion
● TSP is a classic optimization problem in graph theory and algorithms. While greedy
methods provide quick, but suboptimal solutions, brute force guarantees the best result
but is computationally expensive. Dynamic programming helps, but doesn’t change the
NP-complete nature of the problem.
[Link]
v=uuot9ItgTEI&list=PLxCzCOWd7aiHcmS4i14bI0VrMbZTUvlTa&index=32
A Heap Tree is a special type of Binary Tree that satisfies two main properties:
● Structural Property
● Ordering Property
● Rules of ACBT:
📘 Example:
If level 2 is not fully filled and you start filling level 3 → ❌ Not ACBT.
3. Ordering Property
There are two types of heap trees:
1. Max Heap
2. Min Heap
📘 Example:
Max Heap:
10
/ \
8 7
/\ /\
5 46 3
Min Heap:
/\
5 7
/\ /\
8 10 9 11
4. Important Points
● To check if a tree is a Heap:
● If the structural property fails → it’s not a heap, even if ordering is correct.
✅ Answer: Option B
● It is an ACBT and satisfies Parent > Child.
❌ Others fail structural or ordering property.
6. Upcoming Topics
● Heap Insertion
● Deletion
● Heapsort
● Heapify
● Priority Queue
Would you like me to make a shorter one-page exam-style version (with bullet points only)?
🕒 Time Complexity:
Process (simplified):
4. Insert 25 → Swap with parent 14 → then swap again with parent 24 → New root
25
5. Continue similarly…
45
/ \
35 25
/ \ / \
24 14 12 8
/
11
3. Key Points
4. Summary Table
Insertion Insert keys one by one O(n log n) Swap upward after each
insertion
Heapify Place all keys, then O(n) Convert array into heap directly
adjust
📘 Properties:
■ Left child = 2i + 1
■ Right child = 2i + 2
■ Parent = (i - 1) / 2
Options given:
A. [25, 12, 16, 13] ❌ (parent smaller than child)
B. [25, 14, 13, 16] ❌ (violation in Max Heap order)
C. [25, 14, 16, 13, 10, 8, 12] ✅ (correct Max Heap)
D. [25, 14, 12, 13, 10, 8, 16] ❌ (parent smaller than child)
25
/ \
14 16
/ \ / \
13 10 8 12
🧮 First Deletion
● Delete root (25)
● Replace root with last leaf (12) → [12, 14, 16, 13, 10, 8]
🧮 Second Deletion
● Replace with last leaf (8) → [8, 14, 12, 13, 10]
5. Time Complexities
✅ Summary
● Max Heap: Parent ≥ Children
● Important: Know insertion, deletion, heapify process, and time complexities for
exams/interviews.
🔹 What is Heapify?
● Heapify is a method used to build a heap (Max or Min Heap) from an unsorted array.
🔹 Types of Heaps
● Max Heap: Parent ≥ Child
3. Start from bottom non-leaf nodes (since leaves already satisfy heap property).
4. Compare parent with children and swap to maintain Min/Max heap property.
● In heaps, you cannot delete any random element directly because it would break the
Almost Complete Binary Tree (ACBT) structure.
/ \
2 3
/ \ / \
4 5 6 7
Steps:
2. Take the rightmost lowest element (6) and place it at the root.
/ \
4 3
/ \ /
6 5 7
🔹 6. Time Complexity
For n elements,
➡ Total = O(n log n)
✅ Summary
● Can delete only root or rightmost lowest element directly.
🔹 2. Prerequisites
Before learning Heap Sort, you must know:
● Convert the given array into a heap (Min Heap or Max Heap).
/ \
4 10
/ \
9 6
Sorted Output: 2, 4, 6, 9, 10
🔹 5. Time Complexity
Operation Time
🔹 7. Stability
● Heap Sort is Unstable.
Example:
Input → 3A, 3B, 3C
Output → 3C, 3B, 3A (Order changed ❌)
✅ Summary
● Uses heap data structure.
● In-place: ✔️
● Stable: ❌
🧮 Hashing – Notes
[Link]
🔹 1. What is Hashing?
● A method to store and retrieve data in constant time (O(1)).
● Called a mapping technique because it maps large values → small values using
a hash function.
🔹 2. Importance
● Very important for GATE, NET, PSUs, and university exams.
🔹 3. Key Terms
Term Meaning
Search A unique value used to identify a record (e.g., Roll no., Passport
Key no.)
🔹 4. Why Hashing?
● No need to scan the entire array.
● Using a hash function, you can find, insert, or delete data in O(1) time.
🔹 5. Hash Function
● Converts a key (K) into an index of the hash table.
● Common functions:
○ K mod N
○ Mid-Square Method
○ Folding Method
🔹 6. Example (K mod N method)
More examples:
24 4 4
52 2 2
91 1 1
67 7 7
48 8 8
83 3 3
🔹 7. Operations
● Folding Method: Divide key into parts, add parts, use result as index.
Example:
Key = 123456, Table = 0–999
→ Fold: 123 + 456 = 579 → store at index 579.
🔹 9. Collision
● Happens when two keys get the same index.
Example:
52 mod 10 = 2, 62 mod 10 = 2 → both go to index 2 → collision occurs.
● Example:
○ Keys: 32 and 44
Open Hashing Chaining Uses extra memory (like linked lists) outside the table
● When a collision occurs, the new key is added to the chain at that index.
Example:
If both 32 and 44 hash to index 2,
then index 2 → [32 → 44]
➤ Why “Open”?
● Because it uses external (extra) space outside the main table.
➤ Advantages
● Simple to implement.
● Table never gets full (you can keep adding to the list).
➤ Disadvantages
● Uses extra memory.
● Search time increases if long chains form.
● When a collision happens, the algorithm searches for another empty spot in the table
using a formula.
1. Linear Probing
● Formula:
H(i) = (H(key) + i) mod N
Example:
If index 2 is full → check index 3 → 4 → 5 … until an empty spot is found.
2. Quadratic Probing
● Formula:
H(i) = (H(key) + i²) mod N
Example:
Key = 30, Function = K mod 6
3. Double Hashing
● Uses two hash functions:
Formula:
H(i) = (H1(key) + i * H2(key)) mod N
● When two or more keys map to the same index, a linked list (chain) is created at that
index.
● Each index of the hash table contains a pointer to the head node of a linked list.
🔹 2. Example
19 4 4 [19]
10 0 0 [10]
Explanation:
● 42 → index 2
● Insertion usually happens at the beginning of the chain (like linked list insertion).
🔹 4. Advantages
✅ 1. Easy Deletion:
● Works just like deleting a node from a linked list (adjust pointers).
✅ 2. Simple to Implement:
🔹 5. Disadvantages
❌ 1. Extra Memory Required:
● If many keys hash to the same index, a long chain forms → O(n) time.
🔹 6. Time Complexity
Worst case occurs when all keys map to the same index, forming one long chain.
● Formula:
α=Number of elementsNumber of slots\alpha = \frac{\text{Number of elements}}{\
text{Number of slots}}α=Number of slotsNumber of elements
● Example:
4 keys, 5 slots →
α=4/5=0.8\alpha = 4 / 5 = 0.8α=4/5=0.8
h(k) = k mod 10
Then the hash table has indexes from 0 to 9 (since remainder ranges from 0–9).
● 43 mod 10 = 3 → index 3
● 72 mod 10 = 2 → index 2
● 23 mod 10 = 3 → collision → next empty index (4)
🔹 3. Insertion Rule
If the slot is full, move to the next index (i+1).
If you reach the end, wrap around to index 0.
Insert at the first empty slot found.
Example:
🔹 5. Advantages
✅ No extra space — uses existing hash table (closed hashing).
✅ Easy implementation — simple and sequential probing.
✅ Insertion — constant time on average, O(1).
🔹 6. Disadvantages
❌ Searching time →
❌ Secondary Clustering —
When two or more keys follow the same probe sequence while searching for empty slots.
🔹 7. Complexity
Op A W
era v o
tio e r
n r s
a t
g
e
Ins O O
erti ( (
on 1 n
) )
Se O O
arc ( (
hin 1 n
g ) )
Del O O
eti ( (
on 1 n
) )
✅ Summary
● Collision resolved by checking next slot linearly.
● Deletion tricky.
🔹 Question Statement
Keys are inserted into an empty hash table of length 10 using open addressing.
Hash function used:
h(i) = i² mod 10
🔹 Given Keys
1 1 1 1 ❌ 1 1
3 9 9 9 ❌ 9 1
12 14 4 4 ❌ 4 1
4
4 16 6 6 ❌ 6 1
25 62 5 5 ❌ 5 1
5
6 36 6 6 ✅ (occupied by 4) 7 2
18 32 4 4 ✅ (occupied by 12) 8 5
4
20 40 0 0 ❌ 0 1
0
Index Key
0 20
1 1
2 —
3 8
4 12
5 25
6 4
7 6
8 18
9 3
🧩 Concept Recap
● Collision: When two keys hash to the same index.
● Linear probing rule: Move to next index (index + 1) until an empty slot is found.
✅ Final Answers
● Resultant Hash Table:
[20, 1, –, 8, 12, 25, 4, 6, 18, 3]
🔹 Basic Idea
● Quadratic Probing is a collision resolution technique used in open addressing in
hashing.
● When a collision occurs, instead of checking the next cell (like in linear probing), it
checks positions quadratically away.
🔹 Hash Function
Usually given as:
If collision occurs:
🔹 Example
42 2 2 Empty → 42 placed
16 6 6 Empty → 16 placed
91 1 1 Empty → 91 placed
33 3 3 Empty → 33 placed
18 8 8 Empty → 18 placed
27 7 7 Empty → 27 placed
⚙️Working Concept
● Starts from the hash index.
✅ Advantages
● No extra space needed (unlike chaining).
❌ Disadvantages
● No guarantee of finding an empty slot even if table isn’t full.
○ (Two keys with same initial hash follow same probe sequence.)
💡 Terminology
● Collision: When two keys hash to the same index.
🔹 Basic Concept
● Double Hashing is another open addressing collision resolution method.
🔹 Formula
If the first hash gives a collision:
where:
🔹 Example
Keys = {20, 34, 45, 70, 56}
Hash table size (m) = 11
Given functions:
● h₁(k) = k mod 11
● h₂(k) = 8 – (k mod 8)
Key h₁(k h₂(k Insertion Process Final
) ) Position
20 9 — Empty → placed 9
34 1 — Empty → placed 1
45 1 3 1 filled → (1 + 1×3) % 11 = 4 4
70 4 2 4 filled → (4 + 1×2) % 11 = 6 6
Index 0 1 2 3 4 5 6 7 8 9 10
Key — 34 — 56 45 — 70 — — 20 —
⚙️Important Conditions
● h₂(k) and m should be relatively prime (to ensure all slots are probed).
✅ Advantages
● No extra space required (open addressing method).
● Primary clustering removed
(no long chain of filled consecutive slots).
❌ Disadvantages
● Complex to compute (two hash functions needed).
● Need to carefully design h₂(k) so it’s nonzero and relatively prime to table size.
💡 Comparison Summary
🧠 In Short
● Uses two hash functions for collision resolution.
🧩 Question:
We have a set of keys representing employee IDs:
Keys = {0, 2, 5, 7}
Create a Direct Address Table (DAT) for these keys and show how the data is stored and
retrieved.
0 5000
2 7000
5 6500
7 8000
0 5000
1 —
2 7000
3 —
4 —
5 6500
6 —
7 8000
Here, “—” means the slot is empty (no employee with that ID).
A[key] = value
return A[key]
✅ Delete(key):
Just set it to null:
A[key] = null
● Search: O(1)
● Deletion: O(1)
⚠️Limitations
If the key values are very large (say IDs are 1000, 5000, 9000),
we’d need an array of size 9001 — which wastes memory.
That’s why we use hashing for large key ranges.
UNIVERSAL HASHING:
Universal Hashing
[Link]
● But you only care about a small subset (the ones actually in use).
Goal: Achieve fast (constant-time) operations without wasting huge amounts of memory.
We want speed like a bit vector but space efficiency like a list → that’s where hashing
comes in.
🔢 Hashing Basics
● A hash function turns a key (like a username) into an array index.
● If collisions are few, lists stay short → lookup is still very fast.
⚠️The Problem With Fixed Hash Functions
● If your hash function is predictable, an attacker (or bad data) can cause massive
collisions.
● Example: All keys hash to slot 0 → table becomes one long list → time goes
back to O(n).
📊 Mathematical Guarantee
For any two distinct keys x and y:
🚀 Performance
● Expected time per operation: O(1)
It combines:
✅ Efficient space
✅ Constant average lookup time
✅ Robustness against adversarial inputs
⚙️Advantages
● Prevents deliberate collision attacks.
⚠️Disadvantages
🧩 Summary Table
💬 Final Insight
Universal hashing shows how randomness makes systems stronger.
It’s not chaos — it’s controlled unpredictability.
That idea powers not just hashing, but also modern cryptography, secure networks, and
randomized algorithms — where a little bit of randomness protects us from the worst.
ChatGPT said:
○ Initially, all vertices are placed in the priority queue with their tentative distances.
○ The algorithm repeatedly removes (dequeues) the vertex with the minimum
distance value (highest priority).
○ Each step extracts the edge with the smallest weight from the priority queue.
○ The new vertex is added to the tree, and all its connecting edges are
pushed into the queue.
→ This helps in efficiently finding the next smallest edge to add,
ensuring an optimal spanning tree.
Let’s break this down so you’ll never be confused again about Kruskal’s, Prim’s, Dijkstra’s, or
Knapsack.
We’ll go step by step:
11 What each algorithm is,
1️⃣
2️⃣When to use it,
3️⃣A small real-world example, and
4️⃣How to recognize which one fits your problem.
Example:
You’re a network engineer connecting 5 offices with cables of different costs between them.
You want all offices connected with minimum total wire cost.
🧩 Input/Output:
Input: Weighted graph (edges with costs)
Output: Set of edges (tree) with minimum total weight connecting all nodes.
⚖️Key Feature:
● Works edge by edge.
● When you want to start from one specific node (like a central city).
Example:
You’re an electricity company starting from the power station (node A).
You want to connect all cities with minimum wiring cost.
✅ Use Prim’s Algorithm because you start at one node and expand outward.
⚖️Key Feature:
● Works vertex by vertex (adds nearest neighbor each time).
● Example questions:
Example:
You’re using Google Maps —
It finds the fastest route from your location to all nearby destinations.
⚖️Key Feature:
● Works node by node, expanding the shortest known distance.
Example:
You’re a thief with a bag that can carry 10kg.
Items:
⚖️Key Feature:
● 0/1 Knapsack → take or skip item
“Connect all cities with minimum cost” Kruskal’s / Prim’s MST problem (connectivity +
min cost, no cycles)
“Find the shortest route from Karachi to Dijkstra’s Shortest path from one node
Lahore” to another
“Find the shortest routes from Karachi Dijkstra’s Single-source shortest paths
to all cities”
“You start at one node and expand Prim’s MST vertex-based expansion
connections outward”
Kruskal’s Graph (MST) Edges Greedy (sort edges) Min total cost
connecting all
Prim’s Graph (MST) Vertices Greedy (expand from Min total cost
one node) connecting all
You said:
ChatGPT said:
Excellent question — and it’s one that often confuses people at first 👏
0/1 You can either take an item ✅ Dynamic “You can either take the
Knapsack (1) or leave it (0). No Programming laptop or leave it — can’t
fractions allowed. take half.”
Fractional You can take a fraction of ✅ Greedy “You can take half the
Knapsack an item. Algorithm gold bar.”
● You must decide optimally between two choices for each item:
Best value for 5kg using first 3 items depends on solutions for smaller subproblems (like
4kg or 2 items).
● if weight[i] ≤ w
● It’s locally optimal at each step — and this works perfectly for fractional cases.
✅ Summary Table
Knapsack Type Approach Reason
⚠️Quick Check:
If you can’t cut items (0 or 1 only) → Dynamic Programming
If you can take fractions → Greedy
Summary Table
Algorithm Stable Reason
?
1. Quick Sort ❌ Swaps non-adjacent elements
“If I’ve already solved this problem before, I’ll just look up the answer instead of
solving it again!”
Type:
✅ Top-down (uses recursion + caching)
Example:
Let’s take the Fibonacci series example.
👉 Fibonacci formula:
F(n) = F(n-1) + F(n-2)
Memoization version:
“I’ll start solving the smallest problems first, store their answers, and use them to
build up to the big problem.”
Type:
✅ Bottom-up (uses iteration + table)
Example:
Fibonacci using tabulation:
def fib(n):
dp = [0] * (n+1)
dp[0] = 0
dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
💡 Here, dp[i] stores the Fibonacci value for i, and we fill the table step by step.
⚖️Difference Summary
Feature Memoization Tabulation
Order Solves bigger problems first (breaks Solves smaller problems first (builds
down) up)
Best O(n) When the array is already sorted (only one pass
needed).
Average O(n²) Every element is compared multiple times.
2. Insertion Sort
Case Time Complexity Explanation
Average O(n²) Roughly half of the array needs shifting per insert.
3. Selection Sort
Case Time Complexity Explanation
Best O(n²) Always scans the rest of array for the smallest element.
4. Merge Sort
Case Time Complexity Explanation
6. Heap Sort
Case Time Complexity Explanation
Worst O(n log n) Same — heap structure guarantees log n per operation.