1.
Problems and Problem Instances
Understanding the distinction between a general challenge and a specific case is the first step
in algorithm design.
Problem: A general description of the desired relationship between a set of inputs
and outputs (e.g., "Find the maximum number in a list").
Problem Instance: A specific set of input data that satisfies the conditions of the
problem (e.g., "Find the maximum in the list $[12, 45, 7, 23]$").
Generalization: Creating a solution that works for any valid input, regardless of size
or value.
Special Cases (Edge Cases): Scenarios that might break a simple algorithm, such as
an empty list, a list with one element, or a list where all numbers are identical.
2. Classification of Computational Problems
Not all problems are solved the same way. They are categorized based on their goals:
Problem Type Goal Example
Finding a name in a
Search Problems Find a specific value within a collection.
phonebook.
Arrange data in a specific order
Sorting Problems Sorting a list of grades.
(ascending/descending).
Decision Problems Provide a "Yes" or "No" answer. Is $17$ a prime number?
Optimization Find the best solution among many Finding the shortest path
Problems possibilities. between two cities.
3. The Problem-Solving Lifecycle
A disciplined approach follows four critical steps, often called the UPER framework:
1. Understand the Problem: Identify constraints, clarify the "Given" and the "Goal."
2. Plan (Algorithm Development): Break the problem into Subproblems
(Decomposition). Decide on the logic before writing code.
3. Execute: Translate the plan into a programming language (like C).
4. Review (Testing/Refinement): Check for logic errors. Does it handle special cases?
Can it be faster?
4. Analysis of Algorithms: Efficiency and Correctness
Once an algorithm is developed, we must measure its quality.
Efficiency (Complexity)
Efficiency is measured by how resource requirements grow as input size ($n$) increases:
Time Complexity: How long the algorithm takes to run. We use Big O Notation
(e.g., $O(n)$, $O(n^2)$) to describe the "worst-case" scenario.
Space Complexity: The amount of extra memory required during execution.
Correctness
An algorithm is "correct" if it satisfies two conditions:
1. Halting: It must eventually stop (no infinite loops).
2. Accuracy: It must produce the correct output for every valid input instance.
5. Role of Data Structures
Algorithms and Data Structures are inseparable. A Data Structure is a specific way of
organizing data in a computer so it can be used efficiently.
If you need to access elements by index, use an Array.
If you need "First-In-First-Out" logic, use a Queue.
The choice of data structure directly impacts the efficiency of the algorithm.
6. Specification and Validation
To ensure software reliability, we use formal specifications:
Input/Output Specification: A clear definition of what the program expects and
what it promises to return (e.g., "Input: Two integers; Output: Their sum").
Input Validation: The process of checking if the input data is "clean" before
processing it.
o Example: If a user is asked for their age, validation ensures they don't enter a
negative number or a string.
Pre-conditions: Requirements that must be true before an algorithm starts (e.g., "The
input array must be sorted").
Post-conditions: Guarantees of what will be true after the algorithm finishes (e.g.,
"The element $x$ is now at the start of the list").
5-Mark Questions
Q1. Distinguish between a Problem and a Problem Instance with examples.
Answer:
Problem: A general description of a task that needs to be performed. It defines the
relationship between a set of inputs and the required outputs.
o Example: "Sorting an array of integers in ascending order."
Problem Instance: A concrete, specific set of input data provided to a problem.
o Example: "Sorting the specific array $[55, 10, 2, 8]$. "
Key Difference: A problem is abstract and universal, while an instance is specific and
measurable. An algorithm must be designed to solve the problem (all possible
instances), not just one specific instance.
Q2. Explain the role of Pre-conditions and Post-conditions in programming.
Answer:
These are elements of "Design by Contract" that ensure code reliability:
Pre-conditions: These are constraints that must be true before the execution of a
code block or function. If the pre-condition is violated, the function may not work
correctly.
o Example: For a division function div(a, b), the pre-condition is $b \neq 0$.
Post-conditions: These are guarantees or results that the code promises to provide
after execution, provided the pre-conditions were met.
o Example: For a sorting function, the post-condition is that for any index $i$,
$A[i] \leq A[i+1]$.
Q3. Briefly explain the "Understand, Plan, Execute, and Review" steps in
problem-solving.
Answer:
1. Understand: Identify what is given (input), what is required (output), and the
constraints (e.g., memory limits).
2. Plan: Design the logic. This involves breaking the problem into subproblems
(Decomposition) and choosing appropriate data structures.
3. Execute: Write the actual code (implementation) based on the plan.
4. Review: Test the program with various inputs (including edge cases) and refine the
code for better efficiency or readability.
15-Mark Questions
Q1. Discuss the Classification of Computational Problems and the different
Solution Approaches used to solve them.
Answer:
Computational problems are classified based on their core objective:
Types of Problems:
1. Search Problems: Finding a specific element in a structure (e.g.,
Linear/Binary search).
2. Sorting Problems: Organizing data in a specific sequence.
3. Decision Problems: Problems that result in a Boolean (True/False) output
(e.g., "Is $N$ a prime number?").
4. Optimization Problems: Finding the "best" or "most efficient" solution (e.g.,
Shortest path in a map).
Solution Approaches:
1. Greedy Approach: Making the best local choice at each step with the hope of
finding the global optimum.
2. Divide and Conquer: Breaking a problem into smaller identical subproblems,
solving them, and combining the results (e.g., Merge Sort).
3. Dynamic Programming: Storing results of subproblems to avoid redundant
calculations.
4. Randomized Approach: Using a degree of randomness to find a solution
(e.g., Quick Sort with a random pivot).
Q2. Explain Algorithm Analysis in detail. Define Efficiency (Time and Space)
and the importance of Input Validation.
Answer:
Algorithm analysis is the process of predicting the resources required by an algorithm.
Efficiency:
1. Time Complexity: The amount of time an algorithm takes to complete as a
function of input size $n$. It is usually expressed in Big O notation (e.g.,
$O(n^2)$).
2. Space Complexity: The total memory space required by the algorithm,
including the space for input values and auxiliary (extra) space used during
execution.
Correctness: An algorithm is correct if it halts and produces the desired output for all
valid inputs.
Input Validation: This is a crucial step in "Execute" and "Review." It involves
checking if the input data follows the expected format/range before processing.
o Why it matters: It prevents program crashes (e.g., dividing by zero), prevents
security vulnerabilities (e.g., buffer overflows), and ensures the integrity of the
output. If a program expects a positive "Age" and receives "-5", validation
should catch this and prompt the user.
Q3. What is the role of Data Structures in Problem Solving? Explain with an
example of how choosing the wrong structure affects efficiency.
Answer:
Data structures are the physical implementation of an abstract data type. They dictate how
data is organized, stored, and accessed.
Role:
1. Efficiency: Certain structures make specific operations faster. (e.g., Arrays
allow instant access to any element via index).
2. Organization: They provide a way to model real-world relationships (e.g.,
Trees for hierarchical data).
3. Resource Management: Efficient structures use less memory.
Example of Efficiency Impact:
Imagine you need to search for a name in a list of 1 million people.
o Structure A (Unsorted Array): You must check every single name one by
one (Linear Search). In the worst case, you do 1,000,000 checks.
o Structure B (Sorted Array/Binary Search Tree): You can use Binary
Search. In the worst case, you only do about 20 checks ($log_2(1,000,000)$).
o Conclusion: The choice of the "Sorted" structure reduces the work by 99.99%,
demonstrating that the algorithm's power is limited by the data structure it
uses.