Array: Array Data Structure Same Data Type
Array: Array Data Structure Same Data Type
An array is a data structure that stores a collection of elements (values) of the same data type in a
contiguous block of memory. It allows efficient access to its elements using an index.
Features of an Array:
1. Data Type: All elements in an array must be of the same type (e.g., int, float, char).
4. Efficient Access: Any element can be accessed in O(1) time using its index.
2D Array:
A 2D array is a data structure that stores data in rows and columns, resembling a matrix. It is essentially
an array of arrays.
Features of a 2D Array:
2. Indexing: Elements are accessed using two indices: one for the row and another for the column.
3. Contiguous Memory: Though conceptually a matrix, the elements are stored linearly in
memory.
• Linear Search
• Largest Element
• Second Largest
• Largest Three
• Leaders in an array
• Check if Sorted
• Reverse an Array
2. Recursive Case: The part of the function where it calls itself to solve a smaller instance of the
problem.
Example of Recursion
int factorial(int n) {
if (n == 0) { // Base case
return 1;
1. Ensure a Base Case: Always define a condition that stops further recursive calls.
2. Progress Towards the Base Case: Modify the arguments in the recursive call so they move
closer to the base case. For example:
void infiniteRecursion() {
int fact(int n)
{
// wrong base case (it may cause
// stack overflow).
if (n == 100)
return 1;
else
return n*fact(n-1);
}
If fact(10) is called, it will call fact(9), fact(8), fact(7), and so on but the number will never reach
100. So, the base case is not reached. If the memory is exhausted by these functions on the
stack, it will cause a stack overflow error.
How memory is allocated to different function calls in recursion?
When any function is called from main(), the memory is allocated to it on the stack. A recursive
function calls itself, the memory for a called function is allocated on top of memory allocated to
the calling function and a different copy of local variables is created for each function call.
When the base case is reached, the function returns its value to the function by whom it is
called and memory is de-allocated and the process continues.
Recursion VS Iteration
SR
Recursion Iteration
No.
Terminates when the base case becomes Terminates when the condition
1)
true. becomes false.
Every recursive call needs extra space in the Every iteration does not require any
3)
stack memory. extra space.
Divide and Conquer Algorithm can be divided into three steps: Divide, Conquer and Merge .
1. Divide:
Break down the original problem into smaller subproblems.
2. Conquer:
Solve each of the smaller subproblems individually.
If a subproblem is small enough (often referred to as the “base case”), we solve it directly
without further recursion.
3. Merge:
Combine the sub-problems to get the final solution of the whole problem.
Once the smaller subproblems are solved, we recursively combine their solutions to get the
solution of larger problem.
The goal is to formulate a solution for the original problem by merging the results from the
subproblems.
3. Merge Sort:
Some Question:
1. What is the Divide and Conquer algorithm?
Divide and Conquer is a problem-solving technique where a problem is divided into smaller,
more manageable subproblems. These subproblems are solved recursively, and then their
solutions are combined to solve the original problem.
2. What are the key steps involved in the Divide and Conquer algorithm?
The main steps are:
Combine: Merge or combine the solutions of the subproblems to obtain the solution to the
original problem.
3. What are some examples of problems solved using Divide and Conquer?
Divide and Conquer Algorithm is used in sorting algorithms like Merge Sort and Quick Sort,
finding closest pair of points, Strassen’s Algorithm, etc.
4. How does Merge Sort use the Divide and Conquer approach?
Merge Sort divides the array into two halves, recursively sorts each half, and then merges the
sorted halves to produce the final sorted array.