1.
Problems and Problem Instances:
A problem is a general type of task or challenge requiring a solution,
while a problem instance is a specific, concrete example of that
problem with particular input values. For example, the problem is
sorting an array of numbers; an instance would be a specific array like
that needs to be sorted.
Problems
• A General Task:
A problem defines a general challenge or goal, such as sorting, finding the
shortest path, or solving a mathematical equation.
• Defined by Input and Output:
A problem is a set of related problem instances, where each instance is defined
by a set of input data and the desired solution data.
• Conceptual Framework:
Problems often have associated concepts like goals, states, and operations that
define the problem space.
Problem Instances
• Specific Cases: An instance is a particular, concrete manifestation of a
problem.
• Specific Data: It's a specific selection of values for the problem's parameters or
input data.
• Concrete Example: For the problem of sorting, an instance would be a
particular array of integers, with given size and specific values at each
position.
Example
• Problem: Sorting.
• Instance: The array [5, 2, 8, 1].
2. Types of Computational Problems:
Computational problems are categorized into types such as Decision
problems (yes/no answer), Search problems (finding a solution),
Counting problems (counting solutions), Optimization problems
(finding the best solution), and Function problems (computing an
output value). These categories help in analyzing and understanding
the nature and complexity of problems that can be solved using
algorithms and computational models.
Here are the main types of computational problems:
1. Decision Problems
These are problems that have a "yes" or "no" answer.
• Example: Primality testing is a decision problem: given a number, does it have
any divisors other than 1 and itself?
2. Search Problems:
These problems involve finding a particular solution within a given input.
• Example: The Traveling Salesperson Problem (TSP) is a search problem where
the goal is to find the shortest possible route that visits a set of cities and
returns to the origin city.
• 3. Counting Problems:
For these problems, the goal is to determine the number of distinct solutions to
a given problem.
• Example: Given a graph, count the number of ways to color its vertices with a
limited number of colors such that no two adjacent vertices have the same
color.
4. Optimization Problems:
These problems seek the best possible solution among many alternatives, such
as the minimum cost or maximum profit.
• Example: Finding the shortest path in a network or the maximum flow in a
system are common optimization problems.
5. Function Problems:
These are problems where the goal is to compute a specific output value or
function for a given input.
• Example: The factoring problem is a function problem: given a composite
number, find its prime factors.
Decidability and Computability
Problems can also be classified based on whether they can be solved
by an algorithm:
• Computable (or Decidable) Problems:
Problems for which a step-by-step procedure (an algorithm) exists that will
always halt and produce the correct answer in a finite amount of time.
• Non-Computable (or Undecidable) Problems:
Problems for which no algorithm can always provide a correct answer in a finite
amount of time.
3. Classification and Analysis of Problems:
Classification and analysis of problems involves a
two-part process: classifying data into categories
based on features, and analyzing these classifications
to understand patterns and predict future
outcomes. In machine learning, classification refers to
supervised learning tasks where a model learns to
assign new observations to predefined categories, such as binary (two
categories), multi-class (more than two exclusive categories), or multi-
label (multiple non-exclusive categories). Analysis then uses these
classifications to make informed decisions, predict behavior, or
understand relationships within the data.
Classification
This is the process of sorting objects into different groups or
categories based on shared characteristics.
• Objective: To create a model that describes and distinguishes data classes.
• Mechanism: Based on a "training set" of data where the correct category for
each item is known, a model is built to predict the category of new, unseen
data.
• Examples:
• Binary Classification: Assigning an email to either "spam" or "not spam".
• Multi-class Classification: Identifying an image as one of several fruits (apple,
pear, orange).
• Multi-label Classification: Assigning multiple, non-exclusive labels to an image,
like tagging it with "person" and "outdoors".
Problem Analysis
Once data is classified, the next step is to analyze the results to gain
insights.
• Methods:
Classification analysis often uses mathematical techniques like decision trees,
neural networks, or statistical models to understand the data.
• Purpose:
To make decisions, predict future outcomes, or uncover patterns and
relationships within the data.
• Applications:
• Spam Filtering: Analyzing classifications of emails helps refine spam filters to
better identify unwanted messages.
• Credit Risk Analysis: Classifying customers based on their risk level helps
financial institutions make better lending decisions.
• Image Recognition: Analyzing classified images helps in understanding visual
patterns for various applications.
5. Analysis of Algorithms:
Analysis of Algorithms is a fundamental aspect of computer science
that involves evaluating performance of algorithms and programs.
Efficiency is measured in terms of time and space.
Why is Analysis of Algorithm important?
Why is Performance of Algorithms Important ?
There are many important things that should be taken care of, like
user-friendliness, modularity, security, maintainability, etc. Why worry
about performance? The answer to this is simple, we can have all the
above things only if we have performance. So performance is like
currency through which we can buy all the above things. Another
reason for studying performance is - speed is fun!
Why Analysis of Algorithms is important ?
Algorithm analysis is an important part of computational complexity
theory, which provides theoretical estimation for the required
resources of an algorithm to solve a specific computational problem.
Analysis of algorithms is the determination of the amount of time and
space resources required to execute it.
• To predict the behavior of an algorithm for large inputs (Scalable
Software).
• It is much more convenient to have simple measures for the efficiency
of an algorithm than to implement the algorithm and test the
efficiency every time a certain parameter in the underlying computer
system changes.
• More importantly, by analyzing different algorithms, we can compare
them to determine the best one for our purpose.
6. Role of Data Structures in Problem Solving:
Data structures are specialized formats for organizing and storing data
that enable efficient access and modification, acting as a critical
component in problem-solving by optimizing algorithm performance
and reducing complexity. By providing structured ways to manage
data, they facilitate faster and more efficient operations such as
searching, inserting, and deleting, which directly impacts program
speed, memory usage, and overall solution efficiency. Choosing the
right data structure for a problem is essential for designing effective
algorithms and building scalable, high-performance systems.
How Data Structures Aid Problem Solving
• Efficiency:
Data structures organize data in a way that allows for quick processing and
retrieval, leading to faster execution times for algorithms.
• Algorithm Optimization:
They are the foundation of efficient algorithms, enabling programmers to
design solutions that use fewer resources and run faster.
• Data Management:
They provide a systematic approach to managing large amounts of data,
making complex problems more approachable and easier to handle.
• Improved Code Performance:
By optimizing operations like search, insertion, and deletion, data structures
improve the overall performance and resource efficiency of software.
• Code Reusability and Maintainability:
Well-chosen data structures can lead to modular, standardized code
components that are easier to understand, modify, and maintain over time.
Examples in Problem Solving
• Searching:
A hash table allows for average O(1) time complexity for search, insertion, and
deletion operations, which is ideal for problems requiring frequent lookups.
• Queuing and Ordering:
A stack (Last-In, First-Out) or a queue (First-In, First-Out) are used to solve
problems that require specific data processing orders.
• Prioritized Data:
A heap or priority queue is used to efficiently insert or remove elements with
the highest or lowest priority.
• Complex Data Relationships:
Trees and graphs are used for problems involving hierarchical or networked
relationships, such as in file systems or social networks.
7. Problem-Solving Steps (Understand, Plan, Execute, Review):
The 7-step problem-solving model consists of Identify, Analyze,
Develop Solutions, Plan, Implement, Monitor, and Evaluate steps,
guiding you from a broad problem to a concrete, sustainable
solution. This systematic approach ensures that problems are clearly
defined, root causes are found, effective solutions are generated and
chosen, and the positive outcomes are sustained.
1. Identify the Problem
• Define the problem:
Clearly articulate the challenge you're trying to solve, gathering input and
aligning with your team.
• Understand the situation:
Grasp the current conditions surrounding the problem to focus on the right
issue.
2. Analyze the Problem
• Analyze the root cause:
Use methods like the 5 Whys to find the fundamental cause of the problem,
rather than just its symptoms.
• Gather and analyze data:
Collect relevant information to gain a deeper understanding of the problem and
its scope.
3. Develop Solutions
• Explore potential solutions: Brainstorm various possible answers to the
problem, considering different perspectives.
• Select the best solution: Choose the most viable solution based on your
analysis.
4. Plan the Solution
• Create an action plan: Outline the steps needed to implement the chosen
solution effectively.
• Set clear goals: Define the specific objectives for the solution to ensure
everyone is working towards a common aim.
5. Implement the Solution
• Execute the action plan: Put the plan into action to solve the problem.
• Monitor and adjust: Keep track of progress and make adjustments as needed.
6. Monitor and Evaluate
• Track progress: Continuously monitor the implementation of the solution to
ensure it's working as planned.
• Hold the gain: Sustain the improvements achieved by the solution.
7. Review and Improve
• Assess the outcome:
Evaluate whether the solution successfully resolved the problem and achieved
the desired goals.
8. Breaking the Problem into Subproblems:
Breaking a problem into subproblems is a divide-and-conquer or
dynamic programming strategy where a complex problem is divided
into smaller, simpler, and often similar problems. The key steps are:
Divide the main problem into smaller subproblems, Conquer (solve)
these subproblems, and Combine their solutions to get the solution for
the original problem. This approach makes complex problems more
manageable, reduces solution time, and can be applied recursively
until subproblems are trivial to solve.
How it Works
1. Divide: Break the main problem into smaller, similar subproblems.
2. Conquer: Solve these subproblems. This can involve solving them recursively
until they become simple enough to be solved directly.
3. Combine: Integrate the solutions of the subproblems to form the solution for
the original, larger problem.
When to Use It
• Independent Subproblems:
The divide-and-conquer approach is most effective when the subproblems are
independent of each other.
• Overlapping Subproblems:
If subproblems overlap (i.e., the same subproblem needs to be solved multiple
times), dynamic programming is a more efficient technique. It solves and
stores the solutions to overlapping subproblems to avoid redundant
calculations.
Examples
• Merge Sort:
A classic example of divide and conquer, where an array is repeatedly split in
half until each element is in its own sub-array, then merged back in sorted
order.
• Binary Search:
Divides a sorted list in half to search for a target element, conquering each half
until the element is found or determined to be absent.
Benefits
• Simplifies Complexity: Makes complex problems easier to understand and
manage.
• Increases Efficiency: Can significantly reduce the time it takes to solve a
problem by breaking it into more manageable parts.
• Enables Recursion: The approach is well-suited for recursive algorithms, which
call themselves to solve smaller versions of the problem.
9. Input/Output Specification, Validation, Pre and Post
Conditions:
Input/Output specifications describe the data a function expects
(inputs) and returns (outputs). Preconditions are conditions that must
be true before a function is called, outlining requirements for valid
input and system state. Postconditions are conditions that must be
true after a function completes, guaranteeing the function's correct
behavior and state. Validation is the process of checking if these
preconditions and postconditions hold, ensuring data integrity and
program correctness, often by using assertions or specific checks
within the code.
Input/Output Specification
This defines the data that a method or component will receive and
produce.
• Inputs:
The parameters a function takes, including their data types, constraints (e.g.,
range, format), and expected values.
• Outputs:
The return value(s) and any side effects (like modifications to objects or
specific exceptions) that occur after the function executes.
Preconditions
These are requirements that must be met before a function is
executed.
• Purpose:
To inform the caller (the one invoking the function) of the necessary conditions
that must hold for the function to operate correctly.
• Example:
A function to calculate a square root might have a precondition that the input
number must be non-negative (i.e., Arg >= 0), according to Aalborg
Universitet and AdaCore.
Postconditions
These are conditions that must be true after a function has finished
execution.
• Purpose:
To guarantee the expected state of the system and the correctness of the
function's result for the caller.
• Example:
For the square root function, a postcondition could be that the returned value
(result), when squared, is less than or equal to the original argument, as shown
by AdaCore.
Validation
This is the process of verifying that the conditions defined by pre- and
postconditions are actually met.
• How it's done:
• Assertions: Using assert statements in code to check if a condition is true.
• Error Handling: Explicitly checking for invalid input or states and raising
exceptions if conditions are not met.
• Contract Testing: Formalizing the pre- and postconditions and using tools to
automatically check them during execution.