Unit I β Complete Solutions to All Practice Questions
Table of Contents
Practice Questions β Data Structures Basics
Q1. Define the following: (a) Data (b) Data Object (c) Data Type (d) Data Structure (e) ADT.
(a) Data: Raw facts, figures, or values that have no meaning by themselves. Example: 42, "hello", 3.14.
(b) Data Object: A collection of data items (instances) that share a common set of properties. Example: All integers form a data object; all characters form a data object.
(c) Data Type: A classification that specifies:
- The set of values a variable can hold
- The set of operations that can be performed on those values
Example: int in C β values: integers in range $[-2^{31}, 2^{31}-1]$; operations: +, -, *, /, %.
(d) Data Structure: A particular way of organizing and storing data in a computer so that it can be accessed and modified efficiently. It defines the relationship between data elements and the operations allowed on them.
Example: Array (contiguous memory, indexed access), Linked List (nodes with pointers).
(e) ADT (Abstract Data Type): A mathematical model for a data type where the behavior is defined by:
- A set of values (domain)
- A set of operations on those values
- A set of axioms/constraints (rules the operations must follow)
The ADT specifies WHAT operations do, not HOW they are implemented. Example: Stack ADT defines push, pop, peek, isEmpty β without specifying whether an array or linked list is used internally.
Q2. Differentiate between a Data Type and an Abstract Data Type with an example.
| Aspect | Data Type | Abstract Data Type (ADT) |
|---|---|---|
| Definition | Built-in classification provided by the language | Mathematical model defined by behavior |
| Implementation | Implementation is visible and fixed | Implementation is hidden (encapsulated) |
| Focus | What values and operations the language supports | What operations are available, not how they work |
| Example | int, float, char in C |
Stack, Queue, List, Graph |
| User-defined? | Usually built-in | Defined by the programmer |
| Abstraction Level | Low-level | High-level |
Example:
- Data Type
int: You know it uses 4 bytes, stores values $-2^{31}$ to $2^{31}-1$, supports+,-,*,/. - ADT Stack: You know it supports
push(),pop(),peek(),isEmpty(). You do NOT know (or care) if it uses an array or linked list internally.
Q3. Give the ADT definition for a Queue. Specify data, operations, and error conditions.
ADT Queue:
Data:
An ordered collection of elements following FIFO (First In, First Out)
Two markers: 'front' (removal end) and 'rear' (insertion end)
Operations:
create() β Initialize an empty queue
enqueue(element) β Add element at the rear β O(1)
dequeue() β Remove and return the front element β O(1)
front() / peek() β Return the front element without removal β O(1)
isEmpty() β Return true if queue has no elements β O(1)
isFull() β Return true if queue is at capacity β O(1)
size() β Return the number of elements β O(1)
Error Conditions:
dequeue() on empty queue β "Queue Underflow"
enqueue() on full queue β "Queue Overflow"
front() on empty queue β "Queue is Empty"
Axioms:
1. create() produces an empty queue
2. isEmpty(create()) = true
3. dequeue(enqueue(q, x)) returns x if q was empty
4. FIFO: The first element enqueued is the first dequeued
Q4. Classify data structures with a neat diagram. Give two examples of each category.
Data Structures
/ \
Primitive Non-Primitive
/ | | \ / \
int float char bool Linear Non-Linear
/ | | \ / \
Array LL Stack Queue Tree Graph
| Category | Subcategory | Examples |
|---|---|---|
| Primitive | β | int, float, char, bool |
| Non-Primitive β Linear | Static | Array, String |
| Non-Primitive β Linear | Dynamic | Linked List, Stack, Queue |
| Non-Primitive β Non-Linear | β | Tree, Graph |
Alternatively classified as:
| Basis | Type | Examples |
|---|---|---|
| Memory | Static (fixed size) | Array, Stack (array-based) |
| Β | Dynamic (grows/shrinks) | Linked List, BST |
| Organization | Linear (sequential) | Array, Stack, Queue, Linked List |
| Β | Non-Linear (hierarchical/network) | Tree, Graph |
Q5. Differentiate between static and dynamic data structures. When would you prefer one over the other?
| Feature | Static Data Structure | Dynamic Data Structure |
|---|---|---|
| Size | Fixed at compile time | Can grow/shrink at runtime |
| Memory | Allocated on stack or at compile time | Allocated on heap using malloc/free |
| Access | Random access β $O(1)$ | Sequential access β $O(n)$ (for linked structures) |
| Memory Waste | May waste memory (unused slots) | No waste β allocates as needed |
| Examples | Array, Static Stack | Linked List, Dynamic Stack, BST |
| Insertion/Deletion | Expensive β $O(n)$ shifting | Efficient β $O(1)$ pointer changes |
When to prefer:
- Static: When the size is known in advance, and you need fast random access. Example: storing 100 student scores.
- Dynamic: When the size is unpredictable or frequently changing. Example: a playlist where songs are added/removed often.
Q6. Differentiate between linear and non-linear data structures. Give three examples each.
| Feature | Linear | Non-Linear |
|---|---|---|
| Arrangement | Elements in a sequence (one after another) | Elements in hierarchical or network structure |
| Levels | Single level | Multiple levels |
| Traversal | Simple β one pass covers all elements | Complex β multiple paths possible |
| Memory | May or may not be contiguous | Usually non-contiguous |
| Examples | Array, Stack, Queue, Linked List | Tree, Graph, Heap |
Three Linear Examples:
- Array β indexed, contiguous memory
- Stack β LIFO access
- Queue β FIFO access
Three Non-Linear Examples:
- Binary Tree β hierarchical parent-child relationship
- Graph β network of interconnected nodes
- Heap β complete binary tree with heap property
Q7. Explain the relationship: Data β Data Type β Data Structure β ADT.
This forms a hierarchy of increasing abstraction:
-
Data β Raw values with no structure. Example:
5,"hello",true. -
Data Type β Gives meaning to data by defining allowed values and operations. Example:
intmeans5is an integer that supports+,-,*,/. -
Data Structure β Organizes multiple data items with defined relationships and efficient access patterns. Example: An array of integers with indexed access, or a linked list with pointer-based traversal.
-
ADT β The highest abstraction β defines WHAT operations exist without specifying HOW they are implemented. Example: Stack ADT says βpush adds on top, pop removes from topβ β doesnβt specify array or linked list.
Progression: Each level adds more abstraction. Data has no structure β Data Type adds meaning β Data Structure adds organization β ADT hides implementation details entirely.
Q8. Why is choosing the right data structure important? Give a real-world example where a poor choice leads to inefficiency.
Choosing the right data structure is critical because it determines the efficiency of all operations performed on the data.
Example β Contacts App (Search by Name):
| Data Structure | Search Time | Why? |
|---|---|---|
| Unsorted Array | $O(n)$ | Must check every element linearly |
| Sorted Array + Binary Search | $O(\log n)$ | Halves the search space each time |
| Hash Table | $O(1)$ average | Direct lookup by key |
| BST | $O(\log n)$ | Tree-based search |
If you store 1 million contacts in an unsorted linked list, finding a contact requires scanning up to 1 million entries. Using a hash table, the same lookup takes constant time.
Another example β Undo feature: Using a Queue (FIFO) would undo the oldest action first β completely wrong! A Stack (LIFO) correctly undoes the most recent action.
Q9. Define ADT for a βSetβ with operations: union, intersection, difference, membership, insert, delete.
ADT Set:
Data:
An unordered collection of DISTINCT elements (no duplicates)
Operations:
create() β Initialize an empty set
insert(element) β Add element to the set (no-op if already present)
delete(element) β Remove element from the set
membership(element) β Return true if element is in the set
union(S1, S2) β Return a new set containing all elements in S1 OR S2
intersection(S1, S2) β Return a new set containing elements in BOTH S1 AND S2
difference(S1, S2) β Return a new set containing elements in S1 but NOT in S2
isEmpty() β Return true if set has no elements
size() β Return the number of elements
Error Conditions:
delete(element) where element β Set β "Element not found"
Axioms:
1. membership(insert(S, x), x) = true
2. membership(create(), x) = false for all x
3. insert(insert(S, x), x) = insert(S, x) (idempotent β no duplicates)
4. union(S, β
) = S
5. intersection(S, β
) = β
Q10. Match the application with the most suitable data structure.
| Application | Data Structure | Reason |
|---|---|---|
| (a) Browser history | Stack | You go βbackβ to the most recently visited page (LIFO) |
| (b) File system | Tree | Hierarchical directory structure (folders within folders) |
| (c) Social network | Graph | Users are nodes, friendships are edges (many-to-many connections) |
| (d) Printer queue | Queue | Print jobs are served in order of arrival (FIFO) |
| (e) Undo feature | Stack | Undo reverses the most recent action (LIFO) |
Practice Questions β Algorithms
Q1. Define an algorithm. List and explain its five essential characteristics.
Definition: An algorithm is a finite, well-defined sequence of computational steps that transforms input into output to solve a specific problem.
Five Essential Characteristics:
-
Input β Zero or more well-defined inputs are provided. Example: A sorting algorithm takes an array as input.
-
Output β At least one well-defined output is produced. Example: The sorted array is the output.
-
Finiteness β The algorithm must terminate after a finite number of steps. A procedure that runs forever is NOT an algorithm (itβs a βcomputational procedureβ).
-
Definiteness β Each step must be precisely defined with no ambiguity. βSort the array somehowβ is NOT definite. βCompare adjacent elements and swap if out of orderβ IS definite.
-
Effectiveness β Each operation must be basic enough that it can, in principle, be carried out by a person with pencil and paper in finite time. Example: arithmetic operations, comparisons, assignments are effective. βFind the meaning of lifeβ is not.
Q2. Write the pseudo code for finding the GCD of two numbers using the Euclidean algorithm.
Algorithm: EuclideanGCD(a, b)
Purpose: Find the Greatest Common Divisor of two positive integers
Input: Two positive integers a, b
Output: GCD of a and b
1. while b β 0 do
2. temp β b
3. b β a mod b
4. a β temp
5. end while
6. return a
Trace for GCD(48, 18):
| Step | a | b | a mod b |
|---|---|---|---|
| 1 | 48 | 18 | 12 |
| 2 | 18 | 12 | 6 |
| 3 | 12 | 6 | 0 |
| 4 | 6 | 0 | β (stop) |
GCD(48, 18) = 6 β
C Implementation:
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
Q3. Draw a flowchart to check whether a given number is prime or not.
[Start]
β
[Read n]
β
ββ n β€ 1? ββYesβββ [Print "Not Prime"] β [End]
β No
β
[i = 2]
β
ββ i * i β€ n? ββNoβββ [Print "Prime"] β [End]
β Yes
β
ββ n % i == 0? ββYesβββ [Print "Not Prime"] β [End]
β No
β
[i = i + 1]
β
ββββ (back to "i * i β€ n?")
Pseudo code equivalent:
Algorithm: IsPrime(n)
1. if n β€ 1 then return "Not Prime"
2. for i β 2 to βn do
3. if n mod i == 0 then return "Not Prime"
4. end for
5. return "Prime"
Q4. Write pseudo code to reverse an array of $n$ elements.
Algorithm: ReverseArray(A, n)
Purpose: Reverse array A of n elements in-place
Input: Array A[0..n-1], integer n
Output: Array A reversed
1. left β 0
2. right β n - 1
3. while left < right do
4. swap(A[left], A[right])
5. left β left + 1
6. right β right - 1
7. end while
Trace for A = [1, 2, 3, 4, 5]:
| Step | left | right | Swap | Array State |
|---|---|---|---|---|
| 1 | 0 | 4 | A[0]βA[4] | [5, 2, 3, 4, 1] |
| 2 | 1 | 3 | A[1]βA[3] | [5, 4, 3, 2, 1] |
| 3 | 2 | 2 | (stop, left = right) | [5, 4, 3, 2, 1] |
Time: $O(n)$, Space: $O(1)$
Q5. Explain the difference between a flowchart and pseudo code. When would you prefer each?
| Feature | Flowchart | Pseudo Code |
|---|---|---|
| Format | Graphical/visual (boxes, arrows) | Textual (structured English + code-like syntax) |
| Ease of creation | Harder for complex algorithms | Easier for complex algorithms |
| Readability | Intuitive for simple algorithms | Better for detailed logic |
| Modification | Difficult to modify | Easy to modify |
| Documentation | Good for high-level overview | Good for detailed documentation |
| Size | Can become very large and tangled | Compact, scales well |
When to prefer Flowchart:
- Simple algorithms with clear branching
- Explaining logic to non-technical stakeholders
- Understanding control flow visually
When to prefer Pseudo Code:
- Complex algorithms with many steps
- Translating directly to code
- Documenting algorithms in papers/textbooks
Q6. Write an algorithm (in pseudo code) to find the second largest element in an array.
Algorithm: SecondLargest(A, n)
Purpose: Find the second largest element in array A
Input: Array A[0..n-1], integer n (n β₯ 2)
Output: Second largest element
1. if n < 2 then
2. return "Error: Need at least 2 elements"
3. end if
4. largest β max(A[0], A[1])
5. second β min(A[0], A[1])
6. for i β 2 to n-1 do
7. if A[i] > largest then
8. second β largest
9. largest β A[i]
10. else if A[i] > second then
11. second β A[i]
12. end if
13. end for
14. return second
Trace for A = [12, 35, 1, 10, 34, 1]:
| i | A[i] | largest | second |
|---|---|---|---|
| init | β | 35 | 12 |
| 2 | 1 | 35 | 12 |
| 3 | 10 | 35 | 12 |
| 4 | 34 | 35 | 34 |
| 5 | 1 | 35 | 34 |
Result: 34 β
Time: $O(n)$ β single pass, Space: $O(1)$
Q7. Identify which of the following are valid algorithms and why.
(a) βKeep printing 1 foreverβ β β NOT a valid algorithm
- Violates the Finiteness property. An algorithm must terminate after a finite number of steps. This runs infinitely.
(b) βTake two numbers, add them, print the resultβ β β Valid algorithm
- Has input (two numbers), output (the sum), is finite (3 steps), definite (each step is clear), and effective (addition is a basic operation).
(c) βSort the array somehowβ β β NOT a valid algorithm
- Violates the Definiteness property. βSomehowβ is ambiguous β it doesnβt specify HOW to sort. A valid algorithm must have precisely defined steps.
Q8. Write pseudo code for the Tower of Hanoi problem with $n$ disks.
Algorithm: TowerOfHanoi(n, source, auxiliary, destination)
Purpose: Move n disks from source peg to destination peg
Input: n disks, three pegs (source, auxiliary, destination)
Output: Sequence of moves
1. if n == 1 then
2. print "Move disk 1 from " + source + " to " + destination
3. return
4. end if
5. TowerOfHanoi(n-1, source, destination, auxiliary)
6. print "Move disk " + n + " from " + source + " to " + destination
7. TowerOfHanoi(n-1, auxiliary, source, destination)
Trace for n = 3 (AβC, using B as auxiliary):
| Step | Move |
|---|---|
| 1 | Move disk 1 from A to C |
| 2 | Move disk 2 from A to B |
| 3 | Move disk 1 from C to B |
| 4 | Move disk 3 from A to C |
| 5 | Move disk 1 from B to A |
| 6 | Move disk 2 from B to C |
| 7 | Move disk 1 from A to C |
Total moves = $2^n - 1 = 2^3 - 1 = 7$
Time Complexity: $T(n) = 2T(n-1) + 1 = O(2^n)$
Q9. Draw a flowchart for binary search on a sorted array.
[Start]
β
[Read A[], n, key]
β
[low = 0, high = n-1]
β
βββ low β€ high? ββNoβββ [Print "Not Found"] β [End]
β Yes
β
[mid = (low + high) / 2]
β
βββ A[mid] == key? ββYesβββ [Print "Found at mid"] β [End]
β No
β
βββ A[mid] < key? ββYesβββ [low = mid + 1] βββ
β No β
β β
[high = mid - 1] ββββββββββββββββββββββββββββββ
β
ββββ (back to "low β€ high?")
Key idea: Repeatedly halve the search space by comparing the middle element with the key.
Q10. Write an algorithm using proper header, purpose, conditions, and loop notations to find all even numbers in an array.
Algorithm: FindEvenNumbers
Purpose: Find and display all even numbers in an array
Input: Array A[0..n-1] of integers, integer n
Output: All even numbers in the array
Pre-condition: n β₯ 1
Steps:
1. [Initialize] count β 0
2. [Traverse array]
Repeat for i β 0 to n-1:
2.1 [Check even]
if A[i] mod 2 == 0 then
print A[i]
count β count + 1
end if
[End of loop]
3. [Output count]
print "Total even numbers: " + count
4. [Finished]
return
C Implementation:
void findEven(int A[], int n) {
int count = 0;
for (int i = 0; i < n; i++) {
if (A[i] % 2 == 0) {
printf("%d ", A[i]);
count++;
}
}
printf("\nTotal even numbers: %d\n", count);
}
Time: $O(n)$, Space: $O(1)$
Practice Questions β Algorithm Analysis
Q1. Define time complexity and space complexity. Why is time complexity more commonly discussed?
Time Complexity: A function that describes the amount of time (number of basic operations) an algorithm takes as a function of the input size $n$.
Space Complexity: A function that describes the amount of extra memory (beyond the input itself) an algorithm uses as a function of $n$.
Why time is more commonly discussed:
- Memory is reusable β space can be freed and reused, but time once spent is gone forever.
- Time is the main bottleneck β most algorithms run out of time before running out of memory.
- Memory is cheap β modern systems have abundant RAM, but users wonβt wait for slow algorithms.
- Time is more variable β space usage is often straightforward ($O(1)$ or $O(n)$), while time complexity varies widely ($O(\log n)$ to $O(n!)$).
Q2. Explain Big O, Omega, and Theta notations with formal definitions and examples.
Big O β $O(g(n))$ β Upper Bound (Worst Case)
$f(n) = O(g(n))$ if there exist constants $c > 0$ and $n_0 > 0$ such that:
\[f(n) \leq c \cdot g(n) \quad \text{for all } n \geq n_0\]β$f(n)$ grows at most as fast as $g(n)$.β
Example: $3n + 5 = O(n)$ β choose $c = 4, n_0 = 5$: $3n + 5 \leq 4n$ for $n \geq 5$. β
Big Omega β $\Omega(g(n))$ β Lower Bound (Best Case)
$f(n) = \Omega(g(n))$ if there exist constants $c > 0$ and $n_0 > 0$ such that:
\[f(n) \geq c \cdot g(n) \quad \text{for all } n \geq n_0\]β$f(n)$ grows at least as fast as $g(n)$.β
Example: $3n + 5 = \Omega(n)$ β choose $c = 1, n_0 = 1$: $3n + 5 \geq n$ for $n \geq 1$. β
Big Theta β $\Theta(g(n))$ β Tight Bound (Exact Growth Rate)
$f(n) = \Theta(g(n))$ if there exist constants $c_1, c_2 > 0$ and $n_0 > 0$ such that:
\[c_1 \cdot g(n) \leq f(n) \leq c_2 \cdot g(n) \quad \text{for all } n \geq n_0\]β$f(n)$ grows exactly as fast as $g(n)$.β
Example: $3n + 5 = \Theta(n)$ β choose $c_1 = 1, c_2 = 4, n_0 = 5$. β
Q3. Prove that $5n^2 + 3n + 100 = O(n^2)$.
To prove: Find constants $c > 0$ and $n_0 > 0$ such that $5n^2 + 3n + 100 \leq c \cdot n^2$ for all $n \geq n_0$.
Proof:
For $n \geq 1$:
- $3n \leq 3n^2$ (since $n \leq n^2$ for $n \geq 1$)
- $100 \leq 100n^2$ (since $1 \leq n^2$ for $n \geq 1$)
Therefore: $5n^2 + 3n + 100 \leq 5n^2 + 3n^2 + 100n^2 = 108n^2$
So with $c = 108$ and $n_0 = 1$:
\[5n^2 + 3n + 100 \leq 108 \cdot n^2 \quad \text{for all } n \geq 1\]Tighter bound: For $n \geq 10$: $3n \leq 0.03n^2$ and $100 \leq n^2$. So $c = 6.03, n_0 = 10$ also works.
Therefore $5n^2 + 3n + 100 = O(n^2)$. $\blacksquare$
Q4. Prove that $n^2 \neq O(n)$.
Proof by contradiction:
Assume $n^2 = O(n)$. Then there exist constants $c > 0$ and $n_0 > 0$ such that:
\[n^2 \leq c \cdot n \quad \text{for all } n \geq n_0\]Dividing both sides by $n$ (valid since $n > 0$):
\[n \leq c \quad \text{for all } n \geq n_0\]But this is a contradiction β $n$ grows without bound, so for any fixed constant $c$, we can always find $n > c$ (simply choose $n = \lceil c \rceil + 1$).
Therefore, no such $c$ and $n_0$ exist, and $n^2 \neq O(n)$. $\blacksquare$
Q5. Arrange in increasing order of growth rate.
Growth comparison at $n = 100$:
| Function | Value |
|---|---|
| $O(1)$ | $1$ |
| $O(\log n)$ | $\approx 7$ |
| $O(n)$ | $100$ |
| $O(n \log n)$ | $\approx 664$ |
| $O(n^2)$ | $10{,}000$ |
| $O(n^3)$ | $1{,}000{,}000$ |
| $O(2^n)$ | $\approx 1.27 \times 10^{30}$ |
| $O(n!)$ | $\approx 9.33 \times 10^{157}$ |
Q6. Find the time complexity of the nested loop with j += i.
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j += i) {
printf("*");
}
}
The inner loop runs $\lceil n/i \rceil$ times for each value of i.
Total operations = $\sum_{i=1}^{n} \frac{n}{i} = n \cdot \sum_{i=1}^{n} \frac{1}{i} = n \cdot H_n$
where $H_n = 1 + \frac{1}{2} + \frac{1}{3} + β¦ + \frac{1}{n}$ is the Harmonic series.
Since $H_n = \Theta(\ln n)$:
\[\text{Total} = n \cdot \Theta(\ln n) = \Theta(n \log n)\]Answer: $O(n \log n)$
Q7. Find the time complexity of the triple nested loop.
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
// O(1) work
Each loop independently runs $n$ times. By the multiplication rule:
\[n \times n \times n = n^3\]Answer: $O(n^3)$
Q8. Time and space complexity of recursive Fibonacci.
int fib(int n) {
if (n <= 1) return n;
return fib(n-1) + fib(n-2);
}
Time Complexity: $O(2^n)$
The recurrence is $T(n) = T(n-1) + T(n-2) + O(1)$.
The recursion tree is a binary tree where each call spawns two more. At depth $k$, there are up to $2^k$ calls. The tree has depth $n$, giving roughly $2^n$ total calls.
More precisely, $T(n) = O(\phi^n)$ where $\phi = \frac{1+\sqrt{5}}{2} \approx 1.618$ (golden ratio), but $O(2^n)$ is the standard upper bound.
Space Complexity: $O(n)$
At any point, only ONE branch of the recursion tree is active on the call stack. The maximum depth is $n$ (following the leftmost path: $fib(n) \to fib(n-1) \to β¦ \to fib(1)$). So the stack holds at most $n$ frames.
Q9. Differentiate between Best, Average, and Worst case analysis.
| Case | Definition | Usefulness |
|---|---|---|
| Best Case | Minimum time taken (most favorable input) | Rarely useful β too optimistic |
| Average Case | Expected time over all possible inputs | Most realistic but hard to calculate |
| Worst Case | Maximum time taken (least favorable input) | Most commonly used β guarantees upper bound |
Linear Search Example (searching for key in array of $n$ elements):
| Case | When? | Comparisons |
|---|---|---|
| Best | Key is the first element | $1 = O(1)$ |
| Average | Key is equally likely in any position | $\frac{n}{2} = O(n)$ |
| Worst | Key is the last element or not present | $n = O(n)$ |
Bubble Sort Example:
| Case | When? | Comparisons |
|---|---|---|
| Best | Array is already sorted (with optimized version) | $n-1 = O(n)$ |
| Average | Random order | $O(n^2)$ |
| Worst | Array is in reverse order | $\frac{n(n-1)}{2} = O(n^2)$ |
Q10. Explain why we drop constants in Big O notation. Is $O(100n)$ the same as $O(n)$?
Yes, $O(100n) = O(n)$.
Why constants are dropped:
-
Big O describes growth rate, not actual time. We care about how the function behaves as $n \to \infty$, not specific values.
-
Constants depend on hardware. An algorithm taking $100n$ operations on a slow machine may be faster than $n$ operations on an even slower machine. Constants are machine-dependent.
-
Mathematical definition allows it. If $f(n) = 100n$, then $f(n) \leq 100 \cdot n$ for all $n \geq 1$. With $c = 100$, this satisfies the Big O definition for $O(n)$.
-
Asymptotic dominance matters. For large $n$: $100n$ vs $n^2$ β eventually $n^2$ overtakes $100n$ (at $n = 100$). The growth rate of $n^2$ is fundamentally different from $n$, regardless of constants.
Key insight: $O(100n) = O(n)$ but $O(n) \neq O(n^2)$. Constants donβt change the complexity class.
Q11. Find the time complexity of the i = i / 3 loop.
int i = n;
while (i > 0) {
i = i / 3;
}
After $k$ iterations: $i = \frac{n}{3^k}$
The loop stops when $i = 0$ (integer division), which happens when $3^k > n$:
\[k = \lceil \log_3 n \rceil\]Since $\log_3 n = \frac{\log_2 n}{\log_2 3}$, and base changes are just constant factors:
Answer: $O(\log n)$
Note: Dividing by ANY constant $> 1$ gives logarithmic complexity.
Q12. Express $T(n) = 3n^2 + 7n \log n + 100$ in all three notations.
The dominant term is $3n^2$ (since $n^2$ grows faster than $n \log n$).
Big O (upper bound): $T(n) = O(n^2)$
For $n \geq 1$: $3n^2 + 7n\log n + 100 \leq 3n^2 + 7n^2 + 100n^2 = 110n^2$. So $c = 110$, $n_0 = 1$.
Big Omega (lower bound): $T(n) = \Omega(n^2)$
$3n^2 + 7n\log n + 100 \geq 3n^2$ for all $n \geq 1$. So $c = 3$, $n_0 = 1$.
Big Theta (tight bound): $T(n) = \Theta(n^2)$
Since $T(n) = O(n^2)$ AND $T(n) = \Omega(n^2)$, we have $T(n) = \Theta(n^2)$.
\[3n^2 \leq 3n^2 + 7n\log n + 100 \leq 110n^2 \quad \text{for } n \geq 1\]Comprehensive Unit I Practice Set
1. What is the difference between data and information?
| Aspect | Data | Information |
|---|---|---|
| Definition | Raw, unprocessed facts and figures | Processed, organized, meaningful data |
| Meaning | No inherent meaning | Has context and meaning |
| Example | 25, "Delhi", 38.5 |
βTemperature in Delhi is 38.5Β°Cβ |
| Usefulness | Not directly useful for decisions | Useful for decision-making |
| Processing | Input to processing | Output of processing |
Data β Processing β Information
2. Define: (a) Data Type (b) Abstract Data Type (c) Data Structure
(a) Data Type: A classification that specifies the domain of values and the set of operations for a variable. Examples: int, float, char.
(b) Abstract Data Type (ADT): A mathematical model defining a data type purely by its behavior (operations and constraints), independent of implementation. It specifies WHAT, not HOW. Examples: Stack, Queue, List.
(c) Data Structure: A concrete way of organizing, storing, and managing data in memory to enable efficient access and modification. It implements an ADT. Examples: Array, Linked List, Hash Table.
3. Give two real-world examples each of linear and non-linear data structures.
Linear:
- Queue at a movie theater β people wait in a line (FIFO order)
- Stack of plates β you take from the top (LIFO order)
Non-Linear:
- Company organizational chart β hierarchical (tree structure)
- Road network between cities β interconnected (graph structure)
4. Write the ADT for a βBagβ (unordered collection that allows duplicates).
ADT Bag:
Data:
An unordered collection of elements that ALLOWS DUPLICATES
Operations:
create() β Initialize an empty bag
add(element) β Add an element to the bag
remove(element) β Remove one occurrence of element (if exists)
contains(element) β Return true if element is in the bag
count(element) β Return number of occurrences of element
size() β Return total number of elements
isEmpty() β Return true if bag has no elements
clear() β Remove all elements
Error Conditions:
remove(element) where element β Bag β "Element not found"
Axioms:
1. isEmpty(create()) = true
2. size(add(B, x)) = size(B) + 1
3. contains(add(B, x), x) = true
4. count(add(B, x), x) = count(B, x) + 1
Key difference from Set: A Bag allows duplicates. add(B, 5) twice means count(B, 5) = 2.
5. What are the five characteristics of an algorithm?
- Input β Zero or more well-defined inputs
- Output β At least one well-defined output
- Finiteness β Must terminate after a finite number of steps
- Definiteness β Each step must be precisely and unambiguously defined
- Effectiveness β Each step must be basic enough to be carried out mechanically
6. Differentiate between flowchart and pseudo code.
| Feature | Flowchart | Pseudo Code |
|---|---|---|
| Representation | Graphical (shapes + arrows) | Textual (structured English) |
| Complexity handling | Gets messy for complex algorithms | Handles complexity well |
| Ease of modification | Hard to modify | Easy to modify |
| Conversion to code | Requires interpretation | Almost direct translation |
| Standardization | ISO standard symbols exist | No universal standard |
7. Determine the time complexity of each code fragment.
(a) Inner loop runs $i^2$ times: \(\text{Total} = \sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6} = O(n^3)\)
(b) Outer loop halves $i$: $\log n$ iterations. Inner loop always runs $n$ times: \(\text{Total} = n \cdot \log n = O(n \log n)\)
(c) Trick question! Variable j is NOT reset inside the outer loop.
- First outer iteration: inner loop runs $n$ times ($j$ goes 0 to $n$)
- All subsequent iterations: $j$ is already $n$, inner loop runs 0 times.
- Total: $O(n)$, NOT $O(n^2)$!
8. Prove that $O(n^2) + O(n) = O(n^2)$.
Let $f(n) = O(n^2)$ and $g(n) = O(n)$. Then:
- $f(n) \leq c_1 \cdot n^2$ for $n \geq n_1$
- $g(n) \leq c_2 \cdot n$ for $n \geq n_2$
For $n \geq \max(n_1, n_2)$:
\[f(n) + g(n) \leq c_1 \cdot n^2 + c_2 \cdot n \leq c_1 \cdot n^2 + c_2 \cdot n^2 = (c_1 + c_2) \cdot n^2\]With $c = c_1 + c_2$ and $n_0 = \max(n_1, n_2, 1)$:
\[f(n) + g(n) \leq c \cdot n^2 \quad \text{for all } n \geq n_0\]Therefore $f(n) + g(n) = O(n^2)$. $\blacksquare$
General rule: $O(n^a) + O(n^b) = O(n^{\max(a,b)})$ β the higher-order term dominates.
9. If Algorithm A takes $100n$ operations and Algorithm B takes $n^2$ operations, for what values of $n$ is A better?
A is better when $100n < n^2$:
\[100n < n^2 \implies 100 < n \implies n > 100\]| $n$ | Algorithm A ($100n$) | Algorithm B ($n^2$) | Winner |
|---|---|---|---|
| 10 | 1,000 | 100 | B |
| 50 | 5,000 | 2,500 | B |
| 100 | 10,000 | 10,000 | Tie |
| 200 | 20,000 | 40,000 | A |
| 1000 | 100,000 | 1,000,000 | A |
A is better for $n > 100$. B is better for $n < 100$. They tie at $n = 100$.
This illustrates why Big O drops constants β for large inputs, $O(n)$ always beats $O(n^2)$ regardless of the constant factor.
10. Write algorithms for: (a) Sum of digits, (b) Palindrome check, (c) Sieve of Eratosthenes.
(a) Sum of Digits:
Algorithm: SumOfDigits(n)
Input: Positive integer n
Output: Sum of all digits of n
1. sum β 0
2. while n > 0 do
3. sum β sum + (n mod 10)
4. n β n / 10 (integer division)
5. end while
6. return sum
Example: $n = 1234$: $4 + 3 + 2 + 1 = 10$. Time: $O(\log_{10} n)$
(b) Palindrome Check:
Algorithm: IsPalindrome(S, n)
Input: String S of length n
Output: true if S is a palindrome, false otherwise
1. left β 0
2. right β n - 1
3. while left < right do
4. if S[left] β S[right] then return false
5. left β left + 1
6. right β right - 1
7. end while
8. return true
Example: βmadamβ β m=m, a=a, d=d β true. Time: $O(n)$
(c) Sieve of Eratosthenes:
Algorithm: SieveOfEratosthenes(n)
Input: Integer n β₯ 2
Output: All prime numbers from 2 to n
1. Create boolean array isPrime[0..n], initialize all to true
2. isPrime[0] β false, isPrime[1] β false
3. for i β 2 to βn do
4. if isPrime[i] = true then
5. for j β i*i to n step i do
6. isPrime[j] β false
7. end for
8. end if
9. end for
10. for i β 2 to n do
11. if isPrime[i] then print i
12. end for
Time: $O(n \log \log n)$, Space: $O(n)$
11. Explain the classification of data structures with a detailed tree diagram.
Data Structures
/ \
Primitive Non-Primitive
/ | | \ / \
int float char bool Linear Non-Linear
/ | \ / \
Array LL Stack Tree Graph
| Queue |
Singly/Doubly/ BST
Circular AVL/Heap
| Type | Structure | Application |
|---|---|---|
| Array | Contiguous, indexed | Image pixels, matrices, lookup tables |
| Linked List | Nodes with pointers | Music playlists, memory management |
| Stack | LIFO | Undo operations, expression evaluation, recursion |
| Queue | FIFO | Print queues, BFS, CPU scheduling |
| Tree | Hierarchical | File systems, HTML DOM, databases (B-trees) |
| Graph | Network | Social networks, GPS navigation, web crawling |
| Hash Table | Key-value mapping | Dictionaries, caches, symbol tables |
12. Compare Big O, Big Omega, and Big Theta notations.
| Notation | Symbol | Bound Type | Meaning | Analogy |
|---|---|---|---|---|
| Big O | $O$ | Upper bound | $f(n) \leq c \cdot g(n)$ | β€ (at most) |
| Big Omega | $\Omega$ | Lower bound | $f(n) \geq c \cdot g(n)$ | β₯ (at least) |
| Big Theta | $\Theta$ | Tight bound | $c_1 g(n) \leq f(n) \leq c_2 g(n)$ | = (exactly) |
Example with $f(n) = 3n^2 + 5n$:
- $f(n) = O(n^2)$ β and also $O(n^3)$ β (upper bound can be loose)
- $f(n) = \Omega(n^2)$ β and also $\Omega(n)$ β (lower bound can be loose)
- $f(n) = \Theta(n^2)$ β β this is the tightest and most informative
Relationship: $f(n) = \Theta(g(n))$ if and only if $f(n) = O(g(n))$ AND $f(n) = \Omega(g(n))$.
13. Best, Average, and Worst case analysis with Insertion Sort.
Insertion Sort Algorithm: For each element, insert it into its correct position in the already-sorted portion.
Best Case β Already Sorted Array $[1, 2, 3, 4, 5]$:
- Each element is already in the right position
- Inner loop comparison: $A[j] > key$ is false immediately
- Comparisons per element: 1
- Total: $(n-1) \times 1 = n - 1$
- Time: $O(n)$
Worst Case β Reverse Sorted Array $[5, 4, 3, 2, 1]$:
- Each element must be moved to the very beginning
- Element at position $i$ requires $i$ comparisons and shifts
- Total comparisons: $1 + 2 + 3 + β¦ + (n-1) = \frac{n(n-1)}{2}$
- Time: $O(n^2)$
Average Case β Random Array:
- On average, each element is compared with half the sorted portion
- Total: $\frac{1}{2}(1 + 2 + β¦ + (n-1)) = \frac{n(n-1)}{4}$
- Time: $O(n^2)$
| Case | Input | Comparisons | Time |
|---|---|---|---|
| Best | Sorted | $n - 1$ | $O(n)$ |
| Average | Random | $\frac{n(n-1)}{4}$ | $O(n^2)$ |
| Worst | Reverse sorted | $\frac{n(n-1)}{2}$ | $O(n^2)$ |