Data Structure (1)
Data Structure (1)
A recursive function is a function that calls itself to solve a smaller sub-problem of the original problem. This process continues
until it reaches a base case, which stops further recursion.
Example:
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)
Tail recursion is a type of recursion where the recursive call is the last operation performed by the function. This optimization can
improve memory usage since it does not need to store previous states.
Example:
GCD(a, b):
1. If b == 0, return a.
2. Else, compute GCD(b, a % b).
Example (Python):
Example (Python):
def binary_search(arr, low, high, key):
if low > high:
return -1
mid = (low + high) // 2
if arr[mid] == key:
return mid
elif arr[mid] > key:
return binary_search(arr, low, mid - 1, key)
else:
return binary_search(arr, mid + 1, high, key)
Example (Python):
For a function f(n) = f(n-1) + f(n-2), the recursion tree would look like:
f(3)
/ \
f(2) f(1)
/ \
f(1) f(0)
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
def delete_at_front(head):
if not head:
return None
new_head = head.next
if new_head:
new_head.prev = None
return new_head
def delete_at_end(head):
if not head:
return None
if not head.next:
return None
temp = head
while temp.next:
temp = temp.next
temp.prev.next = None
return head
class Node:
def __init__(self, data):
self.data = data
self.next = None
def delete_at_front(head):
if not head:
return None
return head.next # New head
def delete_at_end(head):
if not head or not head.next:
return None
temp = head
while temp.next and temp.next.next:
temp = temp.next
temp.next = None
return head
19. Define BST
A Binary Search Tree (BST) is a binary tree where each node satisfies the following properties:
1. The left subtree contains only nodes with values less than the node's value.
2. The right subtree contains only nodes with values greater than the node's value.
3. Both left and right subtrees are also BSTs.
class TreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
Maximum Height: When the tree is skewed (like a linked list), height = n (number of nodes).
Minimum Height: When the tree is balanced, height = log₂(n) (base-2 logarithm).
24. C Function to Delete a Node After a Specified Node in a Singly Linked List
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
if (arr[mid] == key)
return mid;
else if (arr[mid] > key)
return binarySearch(arr, low, mid - 1, key);
else
return binarySearch(arr, mid + 1, high, key);
}
Example:
1
/ \
2 3
/ \ /
4 5 6
1
/ \
2 3
/ \ / \
4 5 6 7
Algorithm:
C Function:
Maximum Height: A skewed tree (like a linked list) has n levels, so height = n.
Minimum Height: A perfectly balanced tree has height = log₂(n) (base-2 logarithm).
Proof:
Rearranging
ℎ
2 −1=𝑛
, we get
ℎ = log (𝑛 + 1)
2
.
Steps:
Formula:
Distance = Dist(LCA, Node1) + Dist(LCA, Node2)
Given array: A B C D E
Index of C = 2
Parent =
floor((𝑖 − 1)/2)
:
Parent(C) = 𝐵
Left child =
2𝑖 + 1
:
Left(C) = 𝐹
(does not exist here).
Right child =
2𝑖 + 2
:
Right(C) = 𝐺
(does not exist here).
Inorder: D B E A F C G
Preorder: A B D E C F G
1. Root = A.
Postorder Traversal: D E B F G C A.
33. Differences Between Tree Traversal and Graph Traversal
Example Graph:
A -- B -- C
\ /
D --- E
A → B → C → E → D.
Algorithm (Python):
graph = {
'A': ['B', 'D'],
'B': ['A', 'C'],
'C': ['B', 'E'],
'D': ['A', 'E'],
'E': ['C', 'D']
}
visited = set()
dfs(graph, 'A', visited)
Algorithms are categorized based on their approach or application. Here are the main types:
Greedy Algorithm
Dynamic Programming
Backtracking
Brute Force
Recursive Algorithms
Hashing Algorithms
Cryptographic Algorithms
A greedy algorithm makes decisions step-by-step, choosing the option that seems the most optimal at each
Example:
Solution:
1. Pick the largest coin that is less than or equal to the remaining amount.
Dynamic programming (DP) solves problems by breaking them into smaller overlapping subproblems, solving
Example:
Compute the
𝑛
-th Fibonacci number.
Solution (Tabulation):
Example Input:
𝑛=5
Steps:
𝐹[0] = 0, 𝐹[1] = 1, 𝐹[2] = 1, 𝐹[3] = 2, 𝐹[4] = 3, 𝐹[5] = 5
.
Output:
5
.
38. Divide and Conquer Algorithm
A divide and conquer algorithm splits a problem into smaller, independent subproblems, solves them recur
Example:
Solution:
Steps:
Divide: [38, 27, 43, 3, 9] → [38, 27, 43] and [3, 9].
Conquer: Sort [38, 27, 43] → [27, 38, 43]; Sort [3, 9] → [3, 9].
Combine: Merge [27, 38, 43] and [3, 9] → [3, 9, 27, 38, 43].