DS Python Complete QnA
DS Python Complete QnA
1st — Start Here Unit 2: Arrays, Linked Lists, Stacks, Queues ~40%
FALSE. A Stack uses LIFO (Last In, First Out). The last element pushed onto the stack is the first one
popped out. FIFO (First In, First Out) is the principle used by Queues, not stacks. Example: Undo operations
in an editor use a stack — the most recent action is undone first.
■ Exam Tip: This exact True/False appears in Paper 4659 and 4955. Always write LIFO as justification.
U2 | Section A 1 marks
True/False: A doubly linked list uses more memory than a circular linked list. Justify.
TRUE. A Doubly Linked List (DLL) stores two pointers per node — one pointing to the next node and one
pointing to the previous node. A Circular Linked List (CLL) stores only one pointer (next), with the last node
pointing back to the first. Therefore DLL uses more memory per node.
■ Exam Tip: Memory per node: DLL = data + prev + next (3 fields). CLL = data + next (2 fields).
U2 | Section A 3 marks
An Abstract Data Type (ADT) is a mathematical model for a data type that defines:
(1) The data it stores, (2) The operations it supports, and (3) The error conditions associated with those
operations — without specifying the implementation details.
Examples: Stack ADT supports push(), pop(), top(), is_empty(). The user does not need to know whether it
is implemented using an array or linked list.
• Advantage 1 — Encapsulation: Hides internal implementation; user only sees the interface.
• Advantage 2 — Reusability: The same ADT can be implemented differently and swapped without
changing user code.
• Advantage 3 — Modularity: Easier to design, test, and debug large programs.
U2 | Section A 3 marks
Choose the most appropriate data structure for: (i) Browser back/forward navigation (ii)
Hierarchical data (iii) LIFO manner storage.
• (i) Browser back/forward navigation → Stack (back uses pop; URLs stored on stack)
• (ii) Hierarchical data (e.g., file system, org charts) → Tree
• (iii) Last-In-First-Out storage → Stack
■ Exam Tip: Also memorise: Traffic/ticket booking → Queue; Sorted search → BST; Priority tasks →
Heap/Priority Queue.
U2 | Section A 3 marks
How is a Priority Queue different from a normal Queue? Write one application.
Normal Queue: Elements are removed in FIFO order — the element that has been waiting longest is served
first, regardless of its value.
Priority Queue: Each element has an associated priority. The element with the highest (or lowest) priority is
served first, regardless of insertion order.
Key Difference: In a normal queue, order is determined by arrival time. In a priority queue, order is
determined by priority value.
• Application 1: CPU Scheduling — high-priority processes get CPU time first.
• Application 2: Emergency Room Triage — critical patients are attended before minor ones.
• Application 3: Dijkstra's Shortest Path Algorithm — uses a min-priority queue.
■ Exam Tip: Two types: Max-Priority Queue (largest priority served first) and Min-Priority Queue (smallest
first).
U2 | Section A 3 marks
Write a Python code snippet to insert an element at the front of an existing singly linked list.
A new node is created and its next pointer is set to the current head, then the head pointer is updated to the
new node. This is an O(1) operation.
class Node:
def __init__(self, data):
[Link] = data
[Link] = None
Q(a) Convert infix A*(B+D)/E - F*(G+H/K) to postfix. Show all steps. Q(b) Trace stack S of
size 5: push(5), push(3), pop(), top(), push(9), pop(), push(4), push(15), is_empty()
1 A empty A
2 * * A
3 ( *( A
4 B *( AB
5 + *(+ AB
6 D *(+ ABD
7 ) * ABD+
8 / / (pops *) ABD+*
9 E / ABD+*E
10 - - (pops /) ABD+*E/
11 F -F ABD+*E/F
12 * -* ABD+*E/F
13 ( -*( ABD+*E/F
14 G -*( ABD+*E/FG
15 + -*(+ ABD+*E/FG
16 H -*(+ ABD+*E/FGH
17 / -*(+/ ABD+*E/FGH
18 K -*(+/ ABD+*E/FGHK
19 ) -* ABD+*E/FGHK/+
Final Postfix: A B D + * E / F G H K / + * -
Initial [ ] (empty) —
push(5) [5] —
push(3) [ 5, 3 ] —
pop() [5] 3
push(9) [ 5, 9 ] —
pop() [5] 9
push(4) [ 5, 4 ] —
push(15) [ 5, 4, 15 ] —
is_empty() [ 5, 4, 15 ] False
■ Exam Tip: show is_empty() → False because stack has 3 elements. Stack is NOT full (size=5, only 3 used).
U2 | Section B 6 marks
Write the time complexity for: (i) push in stack using linked list (ii) pop in stack using linked
list (iii) delete all from end in singly linked list (iv) search in BST (best case).
pop() in Stack (Linked List) O(1) Remove head — direct pointer update
Delete all from end in Singly LL O(n) Must traverse to (n-1)th node each time; repeated = O(n²) for al
U2 | Section B 11 marks
Q(a) Queue Q had 32 enqueue, 10 first operations (5 raised Empty errors), 15 dequeue. What
is current size? Q(b) Drawbacks of linear queue and how circular queue resolves them. Q(c)
Circular queue of size 4 (array): enqueue(14), dequeue(), enqueue(3), enqueue(7),
enqueue(0), enqueue(9), enqueue(2). Show front and rear.
enqueue(3) [_, 3, _, _] 1 2 —
enqueue(7) [_, 3, 7, _] 1 3 —
■ Exam Tip: In a circular queue of size N (array), max N-1 elements can be stored (one slot kept empty to
distinguish full vs empty).
U2 | Section B 5 marks
Differentiate Singly Linked List and Doubly Linked List. Write Python code to insert at
beginning of singly linked list.
Deletion (given node) O(n) — need prev node O(1) — has prev pointer
U2 | Section B 5 marks
Write Python code to delete a node from the end of a singly linked list.
To delete from end, traverse until the second-to-last node (whose [Link] is None), then set its next to
None.
def delete_from_end(head):
if head is None: # Empty list
return None
if [Link] is None: # Only one node
return None
current = head
while [Link] is not None:
current = [Link] # Stop at 2nd-to-last node
[Link] = None # Remove last node
return head
■ Exam Tip: Time complexity: O(n) — must traverse the entire list.
U2 | Section B 4 marks
U2 | Section B 5 marks
U2 | Section B 4 marks
InsertBeginning(12) 12 head=12
U2 | Section B 4 marks
Differences between Array and Linked List (any 2 points each); Stack and Queue (any 2
points each).
Access Random access O(1) using index Sequential access O(n) — must traverse
Access order Last inserted element removed first First inserted element removed first
Operations push(), pop(), top() enqueue(), dequeue(), front()
U2 | Section B 5 marks
Write Python code to implement a Stack using a Linked List (push and pop functions).
In a linked list-based stack, push inserts at the head (O(1)) and pop removes from the head (O(1)). The head
of the linked list serves as the top of the stack.
class Node:
def __init__(self, data):
[Link] = data
[Link] = None
class Stack:
def __init__(self):
[Link] = None # Head of linked list = top of stack
self._size = 0
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
popped = [Link]
[Link] = [Link] # Move top to next node
self._size -= 1
return popped
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
return [Link]
def is_empty(self):
return [Link] is None
def size(self):
return self._size
★★★★■ | HIGH PRIORITY — 25%
UNIT 4 · Trees, BST & Balanced Search of Exam | 13 Credit Hours
Trees
Unit Introduction
Unit 4 covers tree data structures — from general binary trees to Binary Search Trees (BST) and AVL trees.
A dedicated multi-part BST question (insert/delete/traverse/balance-check) appears in every Section B. Tree
traversals (Inorder, Preorder, Postorder, BFS) and tree construction from traversals are repeatedly asked.
Key themes: Tree terminology, traversals, BST operations (insert/delete 3 cases/search), height-balance
check, AVL rotations, and constructing trees from given traversal sequences.
True/False: In-order traversal of a Binary Search Tree gives a sorted sequence. Justify.
TRUE. The BST property states that for every node: all keys in the left subtree < node key < all keys in right
subtree. In-order traversal visits nodes in Left → Root → Right order. Applying this recursively to a BST
always visits nodes in ascending sorted order.
Example: BST with keys {3, 5, 7} — in-order gives 3, 5, 7.
■ Exam Tip: This is a guaranteed True/False question. Always state the BST property as justification.
U4 | Section A 3 marks
What is an AVL Tree? Explain with a suitable example. Give one application.
AVL Tree (Adelson-Velsky and Landis Tree) is a self-balancing Binary Search Tree in which the difference
between the heights of the left and right subtrees of every node is at most 1. This difference is called the
Balance Factor.
Balance Factor (BF) = Height(Left Subtree) - Height(Right Subtree)
Valid BF values: -1, 0, or +1. If |BF| > 1 after insertion/deletion, rotations are performed to restore balance.
LL Rotation (Right) BF = +2, Left child BF = +1 Single right rotation at unbalanced node
RR Rotation (Left) BF = -2, Right child BF = -1 Single left rotation at unbalanced node
LR Rotation BF = +2, Left child BF = -1 Left rotate left child, then right rotate node
RL Rotation BF = -2, Right child BF = +1 Right rotate right child, then left rotate node
• Application: Database Indexing — AVL trees guarantee O(log n) search, insert, and delete, making
them ideal for database index structures.
• Application: In-memory sorted sets in programming language libraries.
U4 | Section A 6 marks
Differentiate: (i) BFS and DFS tree traversal (ii) Complete and Perfect Binary Tree.
Order Level by level (left to right) Goes deep into one branch first
Data structure used Queue Stack (or recursion)
Definition All levels filled except possibly last; last level filledALL
left levels
to rightcompletely filled; every leaf at same depth
Leaf nodes Last level may be partially filled All leaves at same level
BST with root=7, left: 3→(1, 5→(4,6)), right: 11→(9→8, 13→(12,14)). (a) Write breadth-first
traversal. (b) Insert node 10. (c) Postorder and inorder of result. Is it height-balanced?
Height-Balance Check:
For each node, compute: BF = |h(left) - h(right)|
3 1 (node 1) 2 (3→5→4 or 6) 1 ✓
5 1 1 0 ✓
1,4,6,8,10,12,14
0 0 0 ✓ (leaves)
Conclusion: YES, the tree is height-balanced (AVL property satisfied at every node).
■ Exam Tip: Always check balance factor at every node, not just the root. Show your calculations.
U4 | Section B 5 marks
Algorithm: First element of Preorder = root. Find root in Inorder — elements to its left form left subtree,
elements to its right form right subtree. Recurse.
Step 1: Preorder[0] = a → Root = a
Step 2: In Inorder: x y z a p q r → Left subtree: {x, y, z} | Right subtree: {p, q, r}
Step 3: Next in Preorder for left subtree: y → Left root = y
In {x,y,z}: x y z → Left of y = {x}, Right of y = {z}
Step 4: Next in Preorder for right subtree: q → Right root = q
In {p,q,r}: p q r → Left of q = {p}, Right of q = {r}
Final Tree Structure:
a ← root
/\
yq
/\/\
xzpr
■ Exam Tip: Always start with Preorder to find roots, then split Inorder for subtrees. Practice this algorithm!
U4 | Section B 6 marks
7 Root Root = 7
U4 | Section B 6 marks
BST (root=8, 3→1,6→4,7; 10→14→13). Perform: (i) Insert 2 (ii) Delete 3 (iii) Post-order
traversal (iv) Height-balance check (v) Pre-order traversal.
Original BST:
8
/ \
3 10
/ \ \
1 6 14
/\ /
4 7 13
(i) Insert 2: 2 < 8 → left → 2 < 3 → left → 2 > 1 → right child of 1 → Insert 2 as right child of 1.
(ii) Delete 3 (has TWO children: 1 and 6) → Replace with Inorder Successor (smallest in right subtree of 3) =
4. Delete 4 from its original position. Node 3 is replaced by 4.
Tree after insert 2 and delete 3:
8
/ \
4 10
/ \ \
1 6 14
\ \ /
2 7 13
(iii) Post-order (Left-Right-Root): 2, 1, 7, 6, 4, 13, 14, 10, 8
(v) Pre-order (Root-Left-Right): 8, 4, 1, 2, 6, 7, 10, 14, 13
(iv) Height-balance check: Node 10: h(left)=0, h(right)=2 (10→14→13). BF = |0-2| = 2 > 1 → NOT
height-balanced.
■ Exam Tip: 3 cases for BST delete: (1) Leaf → simply remove. (2) One child → replace node with child. (3) Two
children → replace with inorder successor (or predecessor).
★★★★■ | HIGH PRIORITY — 20%
UNIT 1 · Growth of Functions & of Exam | 8 Credit Hours
Recurrence Relations
Unit Introduction
Unit 1 covers mathematical tools for analyzing algorithm efficiency. The three asymptotic notations (Big-O,
Big-Omega, Big-Theta) appear in every paper. Recurrence relation solving (Recurrence Tree and Master
Theorem) is highly formulaic — learn the methods and you can score full marks on any variant.
Key themes: Prove f(n) = O(g(n)), arrange functions by growth rate, solve T(n) using substitution/recurrence
tree/master theorem.
U1 | Section B 4 marks
O(g(n)) Big-O f(n) ≤ c·g(n) for all n ≥ n■ Upper bound (worst case)
Ω(g(n)) Big-Omega f(n) ≥ c·g(n) for all n ≥ n■ Lower bound (best case)
Θ(g(n)) Big-Theta c■·g(n) ≤ f(n) ≤ c■·g(n) for all n ≥ n■ Tight bound (average case)
Formal Definitions:
• f(n) = O(g(n)) if ∃ constants c > 0, n■ > 0 such that f(n) ≤ c·g(n) for all n ≥ n■
• f(n) = Ω(g(n)) if ∃ constants c > 0, n■ > 0 such that f(n) ≥ c·g(n) for all n ≥ n■
• f(n) = Θ(g(n)) if f(n) = O(g(n)) AND f(n) = Ω(g(n))
■ Exam Tip: If f(n) = Θ(g(n)), then g(n) is the EXACT growth rate of f(n). Big-O is most commonly used in
analysis.
U1 | Section B 6 marks
Big-O Notation: Big-O (O) gives the upper bound on the growth rate of a function. f(n) = O(g(n)) means the
function f(n) grows no faster than g(n) for sufficiently large n. It represents the worst-case time complexity
of an algorithm.
Proof that f(n) = 8n + 5 is O(n):
We need to find constants c > 0 and n■ > 0 such that: 8n + 5 ≤ c·n for all n ≥ n■
Choose c = 9 and n■ = 5:
8n + 5 ≤ 8n + n = 9n (valid when n ≥ 5, because 5 ≤ n)
So 8n + 5 ≤ 9·n for all n ≥ 5.
Therefore, f(n) = 8n + 5 = O(n) with c = 9 and n■ = 5. ✓
■ Exam Tip: Always state: the values of c and n■ explicitly. The examiner expects this proof format.
U1 | Section B 4 marks
U1 | Section B 4 marks
Arrange f1(n) = 2^n, f2(n) = n^(2/3), f3(n) = n·log n, f4(n) = log n in increasing order of
asymptotic complexity.
U1 | Section B 4 marks
U1 | Section B 5 marks
U1 | Section B 5 marks
a = 3, b = 2, f(n) = n²
log_b(a) = log■(3) ≈ 1.585
n^(log_b(a)) = n^(1.585)
Compare: f(n) = n² vs n^1.585 → n² grows faster → f(n) = Ω(n^(1.585 + ε)) for ε ≈ 0.415
Case 3 applies.
Regularity: 3·(n/2)² = 3n²/4 ≤ (3/4)·n² = c·f(n) with c = 3/4 < 1 ✓
T(n) = Θ(n²)
U1 | Section B 4 marks
Tree structure:
Level 0: cn² (1 node)
Level 1: c(n/4)² each = cn²/16 (3 nodes) → Total: 3cn²/16
Level 2: c(n/16)² each (9 nodes) → Total: 9cn²/256 = (9/256)cn²
Pattern: at level i → (3/16)^i · cn² total cost
Number of levels: (n/4^k) = 1 → k = log■(n)
Total cost: Sum of geometric series:
T(n) = cn² · Σ(3/16)^i from i=0 to log■(n)
Since 3/16 < 1, series converges. T(n) = O(cn²) = O(n²)
The leaf level cost: 3^(log■(n)) = n^(log■(3)) ≈ n^0.79 — dominated by root level n².
■ Exam Tip: When the root cost dominates (r < 1 in geometric series), T(n) = Θ(f(n)) — this is Case 3 intuition.
U1 | Section B 5 marks
# Main program
n = int(input("Enter number of elements: "))
lst = []
for i in range(n):
[Link](int(input(f"Enter element {i+1}: ")))
result = recursive_sum(lst, n)
print(f"Sum of list = {result}")
■ Exam Tip: Always define base case first. Here base case is n=0 (empty list). Time complexity: O(n).
★★★■■ | MEDIUM PRIORITY —
UNIT 3 · Recursion 10% of Exam | 4 Credit Hours
Unit Introduction
Unit 3 is short but guaranteed to appear — usually 1 question in Section B involving Python code. Focus on:
Fibonacci (binary recursion), factorial/sum/power (linear recursion), and converting iterative code to
recursive. Know the base case and recursive case for each.
U3 | Section B 4 marks
Binary Recursion: A function that makes TWO recursive calls per invocation. Fibonacci is the classic
example — each call splits into two sub-calls.
def fibonacci(n):
"""Returns nth Fibonacci number using binary recursion"""
if n == 0: # Base case 1
return 0
elif n == 1: # Base case 2
return 1
else: # Binary recursive case — two calls
return fibonacci(n-1) + fibonacci(n-2)
U3 | Section B 4 marks
Convert the iterative power function to recursive: def power(base, exponent): result=1; for i
in range(exponent): result *= base; return result
Analysis of iterative function: Multiplies base by itself exponent times. The recursive equivalent reduces
exponent by 1 each call until exponent = 0 (base case = 1).
# Iterative version (given):
def power_iterative(base, exponent):
result = 1
for i in range(exponent):
result *= base
return result
# Recursive version:
def power(base, exponent):
if exponent == 0: # Base case: anything^0 = 1
return 1
else: # Recursive case: base^n = base * base^(n-1)
return base * power(base, exponent - 1)
# Test
print(power(2, 5)) # Output: 32
print(power(3, 4)) # Output: 81
■ Exam Tip: Pattern for converting iterative to recursive: (1) identify loop termination → base case; (2) identify
loop body → recursive step; (3) return the combination.
U3 | Section B 4 marks
# Test
n = int(input("Enter n: "))
print(f"{n}! = {factorial(n)}")
Trace for factorial(4): 4 × factorial(3) → 4 × 3 × factorial(2) → 4 × 3 × 2 × factorial(1) → 4 × 3 × 2 × 1 = 24
U3 | Section B 4 marks
Unit Introduction
Unit 5 is the lowest-weightage unit but usually yields 3–6 easy marks in Section B. Focus on: heap
properties, max-heap vs min-heap, array representation, and building a max-heap. Also know how Binary
Heap differs from BST.
U5 | Section B 3 marks
Explain any two properties of Binary Heap. How is it different from a BST?
Find Max/Min O(1) — always at root O(n) or O(log n) for sorted path
Primary use Priority Queue, Heap Sort Searching, sorting, ordered data
U5 | Section B 4 marks
For heap of height h, what is the maximum and minimum number of elements?
Formula Explanation
Minimum elements in height-h heap 2^h Only the last level has just 1 node (root at h=0: 1 node = 2^
Maximum elements in height-h heap 2^(h+1) - 1 All levels completely filled (perfect binary tree)
Examples:
• Height 0: min = 1, max = 1
• Height 1: min = 2, max = 3
• Height 2: min = 4, max = 7
• Height 3: min = 8, max = 15
■ Exam Tip: Formula to memorise: min = 2^h, max = 2^(h+1) - 1. These appear directly in exam questions.
U5 | Section B 6 marks
Heap: node at index i Left child: 2i+1 | Right child: 2i+2 | Parent: (i-1)//2
Infix to Postfix rule Higher/equal precedence pops before pushing new operator
Stack uses FIFO FALSE Stack uses LIFO — Last In First Out
Queue uses LIFO FALSE Queue uses FIFO — First In First Out
In-order BST = sorted sequence TRUE BST property: left < root < right, traversed in order
Doubly LL uses more memory than singly LL TRUE Extra prev pointer per node
Doubly LL uses more memory than circular LL TRUE CLL has only one pointer; DLL has two
Recursive is always more efficient than iterative FALSE Recursion has function call overhead; iterative can be faster
O(n log n) is faster than O(n²) TRUE n log n grows slower than n² for large n
Master method solves all recurrences FALSE Only works for T(n) = aT(n/b) + f(n) form
Time complexity of insertion sort is O(n log n) FALSE Insertion sort is O(n²) worst case; O(n) best case
■ Tree Terminology
Root: topmost node. Leaf: node with no children. Height of tree: longest path from root to leaf. Depth of node:
distance from root. Degree of node: number of children. Height of leaf node = 0. Height of empty tree = -1.
Remember: Unit 2 (Stacks/Queues/Linked Lists) + Unit 4 (Trees/BST) = 65% of the paper. Show all
steps in trace questions. Draw diagrams for BST and Heap. All the best! ■