2 Algorithms and Solution Design
A practical guide to analyzing problems, designing algorithms, representing solutions with pseudocode and flowcharts, and testing solutions for correctness and efficiency.
From Problem to
An is a finite, ordered set of precise steps that transforms into the required . Algorithmic problem solving begins before programming: first determine exactly what problem must be solved, then design and test a solution. Computational thinking supports this process through , abstraction, pattern recognition, and design.
A useful workflow is:
Understand and restate the problem.
Identify the inputs and required outputs.
Identify rules, assumptions, and constraints.
Break the problem into manageable parts.
Design a step-by-step solution.
Represent the solution with or a .
Test the solution with normal, boundary, and invalid data.
Improve the solution if it is incorrect, unclear, or inefficient.
A computer cannot reliably solve a vague problem. The problem definition must be precise enough that two people would interpret it in the same way.
Takeaway: Clarify the problem before deciding how to code it.
Analyzing the Problem
Restating a task in your own words removes unnecessary details and reveals the central decision or calculation. For example, a store problem can be restated as follows: given a purchase amount, reduce it by when , and otherwise leave it unchanged.
divides the task into smaller subproblems. The discount example can be divided into these parts:
Read the purchase amount.
Determine whether the amount qualifies for the discount.
Calculate the discount when applicable.
Calculate the final price.
Display the result.
Each part should have a clear purpose and be simple enough to describe or test independently.
An assumption is a condition accepted as true when the problem does not specify otherwise. Relevant assumptions might include that the purchase amount is nonnegative, that the discount is applied before tax, and that monetary results are rounded to two decimal places. Stating assumptions prevents different implementations from making incompatible decisions.
Abstraction focuses attention on the important features of a problem while leaving out unnecessary detail. Pattern recognition can reveal that a new task resembles a previously solved task, allowing a known strategy to be adapted carefully.
Takeaway: Restatement, , abstraction, pattern recognition, and explicit assumptions turn a broad task into a precise set of responsibilities.
Inputs, Outputs, and Constraints
A precise specification separates the information supplied to the from the result it must produce. For the discount example, the is a nonnegative purchase amount represented as a decimal or real number, and the is the final price after any eligible discount.
When , calculate:
Otherwise, calculate:
A is a limit or rule that the solution must obey. Examples include a score restricted to the range from to , a date required to use the format YYYY-MM-DD, a memory limit, a response-time limit, or a business rule such as a discount threshold.
Validation checks whether supplied data satisfies the constraints. For example, a purchase amount below is invalid and should be rejected or requested again. Validation is different from processing: validation determines whether data is acceptable, while processing calculates a result for valid data.
Constraints may describe data ranges, formats, resources, time, business rules, technology, safety, or privacy. They affect design choices; for example, a method suitable for a small list may not be suitable for millions of records.
Takeaway: Specify inputs, outputs, processing rules, data types, and constraints before designing the steps.
Designing the Solution
A well-designed produces the required for every valid . It should be correct, unambiguous, finite, ordered, general, efficient, and testable. Efficiency considers the time and memory used as the amount of grows.
Most introductory solutions combine three :
Sequence: instructions execute in a logical order.
Selection: a condition determines which instructions execute.
Iteration: instructions repeat while or until a condition is satisfied.
For example, a solution can use sequence to read a value and calculate a result, selection to choose whether a discount applies, and iteration to request another value while the current value is invalid.
These structures are complementary. Sequence establishes order, selection handles alternatives, and iteration handles repetition. Combining them allows one to validate data, make decisions, perform calculations, and produce .
A solution should also terminate appropriately. An iteration condition must eventually become false for valid inputs, unless continued repetition is an intentional part of the design.
Takeaway: Check not only what an calculates, but also whether its control flow is ordered, finite, and appropriate for all valid inputs.
Representing Algorithms
expresses algorithmic logic without committing to a particular programming language. Use one instruction per line, meaningful names, precise conditions, and indentation inside decisions and loops. Make the beginning, end, inputs, outputs, and repeated sections clear.
A discount solution can be described in this order:
Start and read the purchase amount.
While the amount is less than , display an error and request another amount.
If the amount is at least , calculate the final price by multiplying it by .
Otherwise, keep the original amount as the final price.
Display the final price rounded to two decimal places.
End.
A presents the same logic visually. Use an oval or rounded rectangle for the start and end, a parallelogram for or , a rectangle for a process or calculation, and a diamond for a decision. Connect symbols with arrows and label decision branches, usually with “Yes” and “No.”
is often quicker to edit, while a can make paths, decisions, and loops easier to see. Both representations should express the same underlying logic.
When designing a , begin with one clearly labeled start symbol, connect symbols with arrows, place one action or calculation in each process box, put a question rather than an action in a decision diamond, label every branch, and ensure that every possible path reaches an appropriate outcome.
Takeaway: Choose a representation that makes the ’s steps and control flow easy to inspect.
Dry Runs and Testing
A traces an manually with sample data. Suppose the purchase amount is . The validation succeeds, the condition is true, and the calculation is:
The expected displayed result is $108.00. Testing a second value such as checks the other branch and should produce $80.00.
A useful test set includes:
Typical cases: ordinary valid inputs.
Boundary cases: values at or near a limit, such as , , and .
Invalid cases: values that violate a , such as .
Special cases: zero, an empty collection, or the largest permitted value.
For the discount rule, expected outcomes include:
produces $80.00.
produces $90.00.
produces $135.00.
produces $0.00.
produces an error and requires re-entry.
A occurs when an runs but produces the wrong result. A syntax error occurs when program code violates the rules of its language. Dry-running helps find logic errors before implementation, while systematic testing checks whether the completed solution behaves as expected. Testing compares actual results with expected results and should guide improvements when discrepancies appear.
Takeaway: Test both sides of every decision and include values at, near, and outside important limits.