Module 1
Module 1
Module-1
1. Introduction
1.1 What is an algorithm?
Algorithm: It is a sequence of unambiguous instructions for solving a problem.
Notion of an algorithm
Example-1
ALGORITHM gcd(m, n)
//Computes gcd(m, n) by Euclid’s algorithm
//Input: Two nonnegative, non zero integers m and n
CSE@HKBKCE 1
DAA Module-1
There are several algorithms for computing the greatest common divisor. Let us look at
the other two methods for this problem.
The first is simply based on the definition of the greatest common divisor of m and n as
the largest integer that divides both numbers evenly
Note that unlike Euclid's algorithm, this algorithm, in the form presented, does not work
correctly when one of its input numbers is zero. This example illustrates why it is so
important to specify the range of an algorithm's inputs explicitly and carefully.
Example:
Thus, for the numbers 60 and 24, we get
60=2·2·3·5
24=2·2·2·3
gcd(60, 24) = 2. 2. 3 = 12
CSE@HKBKCE 2
DAA Module-1
a simple algorithm for generating consecutive primes not exceeding any given integer n. It
was probably invented in ancient Greece and is known as the sieve of Eratosthenes (ca.
200 B.C.).
Algorithms can be considered to be procedural solutions to problems. These solutions are not
answers but specific instructions for getting answers
CSE@HKBKCE 3
DAA Module-1
The vast majority of algorithms in use today are still destined to be programmed for a computer
closely resembling the von Neumann machine. Its central assumption is that instructions are
executed one after another, one operation at a time. Accordingly, algorithms designed to be
executed on such machines are called sequential algorithms. Newer computers that can execute
operations concurrently, i.e., in parallel. Algorithms that take advantage of this capability are
called parallel algorithms.
Some algorithms do not demand any ingenuity in representing their inputs. But others are require
ingenious data structures
• They provide guidance for designing algorithms for new problems, i.e., problems for
which there is no known satisfactory algorithm.
• Algorithms are the cornerstone of computer science. Algorithm design techniques
make it possible to classify algorithms according to an underlying design idea; therefore,
they can serve as a natural way to both categorize and study algorithms
CSE@HKBKCE 4
DAA Module-1
Although tracing the algorithm's performance for a few specific inputs can be a very worthwhile
activity, it cannot prove the algorithm's correctness conclusively. But in order to show that an
algorithm is incorrect, you need just one instance of its input for which the algorithm fails.
If the algorithm is found to be incorrect, you need to either redesign it under the same decisions
regarding the data structures, the design technique, and so on, or, in a more dramatic reversal,
to reconsider one or more of those decisions The notion of correctness for approximation
algorithms is less straightforward than it is for exact algorithms. For an approximation algorithm,
we usually would like to be able to show that the error produced by the algorithm does not exceed
a predefined limit
Analyzing an Algorithm
there are two kinds of algorithm efficiency: time efficiency and space efficiency.
• Time ~fficiency indicates how fast the algorithm runs
• space efficiency indicates how much extra memory the algorithm needs.
Coding an Algorithm
CSE@HKBKCE 5
DAA Module-1
There are two kinds of efficiency time efficiency and space efficiency.
• Time efficiency, also called time complexity,indicates how fast an algorithm in question
runs, or the time required by an algorithm to run to completion
• Space efficiency, also called space complexity, refers to the amount of memory units
required by the algorithm in addition to the space needed for its input and output that is
the total memory required by an algorithm to run to completion
Almost all algorithms run longer on larger inputs. For example, it takes longer to sort larger arrays,
multiply larger matrices, and so on. Therefore an algorithm’s efficiency can be analyzed as a
function of some parameter n indicating the algorithm’s input size.
The choice of an appropriate size metric can be influenced by operations of the algorithm in
question. For example
1. Consider the input’s size for a spell-checking algorithm ,If the algorithm examines
individual characters of its input, the size is measured by the number of characters. If it
works by processing words, then the number of words in the input should be counted.
2. Algorithms solving problems such as checking primality of a positive integer n. Here, the
input is just one number, and it is this number’s magnitude that determines the input. In
such situations, it is preferable to measure size by the number b of bits in the n’s binary
representation: b = log2 n + 1.
One possible approach is to count the number of times each of the algorithm’s operations is
executed. This approach is both excessively difficult and, as we shall see, usually unnecessary.
Therefore it is sufficient to identify the most important operation of the algorithm, called the basic
operation, the operation contributing the most to the total running time, and compute the number
of times the basic operation is executed.
Basic operation of an algorithm is usually the most time-consuming operation in the algorithm’s
innermost loop.
Example:
1. Most sorting algorithms work by comparing elements (keys) of a list being sorted with
each other; for such algorithms, the basic operation is a key comparison.
CSE@HKBKCE 6
DAA Module-1
2. Algorithms for mathematical problems typically involve some or all of the four
arithmetical operations: addition, subtraction, multiplication, and division. Of the four, the
most time-consuming operation is division, followed by multiplication and then addition
and subtraction.
Thus, the established framework for the analysis of an algorithm’s time efficiency suggests
measuring it by counting the number of times the algorithm’s basic operation is executed on inputs
of size n.
Application: Let Cop be the execution time of an algorithm’s basic operation on a particular
computer, and let C(n) be the number of times this operation needs to be executed for this
algorithm. Then we can estimate the running time T (n) of a program implementing this algorithm
on that computer by the formula
T (n) ≈ Cop C(n).
1
assuming that C(n) = 2 ∗ 𝑛 ∗ (𝑛 − 1), how much longer will the algorithm run if we double its
input size.
It has to be noted that the value of cop was cancelled out in the ratio. Also note that 1/2 , the
multiplicative constant in the formula for the count C(n), was also cancelled out. It is for these
reasons that the efficiency analysis framework ignores multiplicative constants and concentrates
on the count’s order of growth within a constant multiple for large-size inputs.
For large values of n, it is the function’s order of growth that counts. Table 1.1 contains values of
a few functions particularly important for analysis of algorithms. The magnitude of the numbers
in Table 1.1 has a profound significance for the analysis of algorithms.
Table 1.1 Values (some approximate) of several functions important for analysis of algorithms
CSE@HKBKCE 7
DAA Module-1
The function growing the slowest among these is the logarithmic function. We can expect a
program implementing an algorithm with a logarithmic basic-operation count to run practically
instantaneously on inputs of all realistic sizes
The exponential function 2n and the factorial function n! Both these functions grow so fast that
their values become very large even for rather small values of n.
There are many algorithms for which running time depends not only on an input size but also on
the specifics of a particular input. Consider, as an example, sequential search. This algorithm
searches for a given item (some search key K) in a list of n elements by checking successive
elements of the list until either a match with the search key is found or the list is exhausted.
{
if(a[i]=k
return i
}
retrun -1
}
CSE@HKBKCE 8
DAA Module-1
In the worst case, when there are no matching elements or the first matching element happens to
be the last one on the list, the algorithm makes the largest number of key comparisons among all
possible inputs of size n: Cworst(n) = n.
The worst-case efficiency of an algorithm is its efficiency for the worst-case input of size n, which
is an input (or inputs) of size n for which the algorithm runs the longest among all possible inputs
of that size. The worst-case analysis provides very important information about an algorithm’s
efficiency by bounding its running time from above. In other words it guarantees that for any
instance of size n, the running time will not exceed Cworst(n .).
The best-case efficiency of an algorithm is its efficiency for the best-case input of size n, which
is an input (or inputs) of size n for which the algorithm runs the fastest among all possible inputs
of that size. For example, the best-case inputs for sequential search are lists of size n with their
first element equal to a search key; accordingly, Cbest(n) = 1 for this algorithm.
if p = 1 (the search must be successful), the average number of key comparisons made by sequential
search is (n + 1)/2; that is, the algorithm will inspect, on average, about half of the list’s elements.
If p = 0 (the search must be unsuccessful), the average number of key comparisons will be n
because the algorithm will inspect all n elements on all such inputs.
CSE@HKBKCE 9
DAA Module-1
Let t (n) and g(n) can be any nonnegative functions defined on the set of natural numbers.
• t (n) - algorithm’s running time (usually indicated by its basic operation count C(n)), and
• g(n) will be some simple function to compare the count with
1.4.1 O(big oh) –Notation
Informally, O(g(n)) is the set of all functions with a lower or same order of growth as g(n)
Definition: A function t (n) is said to be in O(g(n)), denoted t (n) ∈ O(g(n)),if t (n) is bounded
above by some constant multiple of g(n) for all large n, i.e., if there exist some positive constant c
and some nonnegative integer n0 such that
Note: The definition gives us a lot of freedom in choosing specific values for constants c and n0.
Definition : A function t (n) is said to be in (g(n)), denoted t (n) ∈ (g(n)), if t (n) is bounded
below by some positive constant multiple of g(n) for all large n, i.e., if there exist some positive
constant c and some nonnegative integer n0 such that
CSE@HKBKCE 10
DAA Module-1
Definition : A function t (n) is said to be in (g(n)), denoted t (n) ∈ (g(n)), if t (n) is bounded
both above and below by some positive constant multiples of g(n) for all large n, i.e., if there
exist some positive constants c1 and c2 and some non negative integer n0 such that
c2g(n) ≤ t (n) ≤ c1g(n) for all n ≥ n0.
CSE@HKBKCE 11
DAA Module-1
Proof
Since t1(n) O(g1(n)), there exist some positive constant c1 and some non negative integer n1
such that
t1 (n) c1g(n) for all n ≥ n1
similarly Since t2(n) O(g2(n)), there exist some positive constant c2 and some non negative
integer n2 such that
t2 (n) c2g(n) for all n ≥ n2
Let us denote c3= max{c1,c2} and consider n max {n1,n2} so that we can use both inequalities
CSE@HKBKCE 12
DAA Module-1
nlogn Linearithmic Divide and conquer algorithms example merge sort quick
sort
n2 quadratic Algorithms with two embedded loop. Elementary sorting,
operations on n*n matrix
n3 cubic Algorithms with three embedded loops. Example
algorithms from linear algebra. Matrix multiplication
2n Exponential Algorithms that generates all subsets of n elements set
n! Factorial Algorithms that generates permutation of n element set
Example 1: the problem of finding the value of the largest element in a list of n numbers. we
assume that the list is implemented as an array. The pseudo code is given below
CSE@HKBKCE 13
DAA Module-1
Basic operation- . There are two operations in the loop’s body, the comparison A[i]> maxval and
the assignment maxval←A[i]. Since the comparison is executed on each repetition of the loop and
the assignment is not, we should consider the comparison to be the algorithm’s basic operation.
Since the number of comparison is the same for all array of size n , we need not have to distinguish
between best, worst and average cases
Let us denote C(n) -the number of times this comparison is executed. The algorithm makes one
comparison on each execution of the loop, which is repeated for each value of the loop’s variable
i within the bounds 1 and n − 1, inclusive. Therefore, we get the following sum for C(n):
Example -2:
Consider the element uniqueness problem: To check whether all the elements in a given array of
n elements are distinct. This problem can be solved by the following algorithm.
CSE@HKBKCE 14
DAA Module-1
3. The number of element comparisons depends not only on n but also on whether there are
equal elements in the array and, if there are, which array positions they occupy. So we will
limit our investigation to the worst case only.
By definition, the worst case input is an array for which the number of element comparisons
Cworst(n) is the largest among all arrays of size n. An inspection of the innermost loop reveals
that there are two kinds of worst-case inputs. Arrays with no equal elements and arrays in which
the last two elements are the only pair of equal elements.
For such inputs, one comparison is made for each repetition of the innermost loop, i.e., for each
value of the loop variable j between its limits i + 1 and n − 1; this is repeated for each value of the
outer loop, i.e., for each value of the loop variable i between its limits 0 and n − 2. Accordingly,
we get
Example 3: Given two n × n matrices A and B, find the time efficiency of the algorithm for
computing their product C = AB.
CSE@HKBKCE 15
DAA Module-1
There is just one multiplication executed on each repetition of the algorithm’s innermost loop,
which is governed by the variable k ranging from the lower bound 0 to the upper bound n − 1.
Therefore, the number of multiplications made for every pair of specific values of variables i and
j is
and the total number of multiplications M(n) is expressed by the following triple sum:
If we now want to estimate the running time of the algorithm on a particular machine, we can do
it by the product
Where cm is the time of one multiplication on the machine in question.We would get a more
accurate estimate if we took into account the time spent on theadditions, too:
where ca is the time of one addition. Note that the estimates differ only by their multiplicative
constants and not by their order of growth.
Example 4: The following algorithm finds the number of binary digits in the binary representation
of a positive decimal integer.
ALGORITHM Binary(n)
//Input: A positive decimal integer n
//Output: The number of binary digits in n’s binary representation
count ←1
while n > 1 do
count ←count + 1
n←_n/2_
CSE@HKBKCE 16
DAA Module-1
return count
The most frequently executed operation here is not inside the while loop but rather the comparison
n > 1 that determines whether the loop’s body will be executed.
the loop variable takes on only a few values between its lower and upper limits; therefore, we
have to use an alternative way of computing the number of times the loop is executed. Since the
value of n is about halved on each repetition of the loop, the answer should be about log2 n.
Recursive Algorithms
EXAMPLE 1 Compute the factorial function F(n) = n! for an arbitrary nonnegative integer n.
Since
n!= 1 . . . . . (n − 1) . n = (n − 1)! . n for n ≥ 1
and 0!= 1 by definition, we can compute F(n) = F(n − 1) . n with the following
recursive algorithm.
ALGORITHM F(n)
{
//Computes n! recursively
//Input: A nonnegative integer n
//Output: The value of n!
if n = 0 return 1
else return F(n − 1) * n
}
consider n as an indicator of this algorithm’s input size
CSE@HKBKCE 17
DAA Module-1
The initial condition tells us the value with which the sequence starts. We can obtain this value
by inspecting the condition that makes the algorithm stop its recursive calls:
if n = 0 return 1.
This tells us two things.
1. since the calls stop when n = 0, the smallest value of n for which this algorithm is
executed is 0
2. when n = 0, the algorithm performs no multiplications.
Therefore the initial condition is M(0)=0
CSE@HKBKCE 18
DAA Module-1
This problem has a very good recursive solution . Assume that there are n disks . first move n-1
disk from tower A to tower C . Now move the largest disk from tower A to B. Then move the
remaining n-1 disk from tower C to tower B
Algorithm TowersOfHanoi(n, S, D, T)
2 // Move the top n disks from tower S to tower D.
3{
4 if (n > 1) then
5 {
6 TowersOfHanoi(n -1,S , T, D);
7 write ("move top disk from tower", S, "to top of tower", D);
9 TowersOfHanoi(n-1, T, D, S);
10 }
11 }
When a recursive algorithm makes more than a single call to itself, it can be useful for analysis
purposes to construct a tree of its recursive calls. In this tree, nodes correspond to recursive calls,
and we can label them with the value of the parameter. For the Tower of Hanoi example, the tree
is given in Figure 1.5. By counting the number of nodes in the tree, we can get the total number of
calls made by the Tower of Hanoi algorithm
𝑛−𝑖
=2n −1
C(n)= ∑ 2l where l is the level in the tree in Figure 1.5
l=0
CSE@HKBKCE 19
DAA Module-1
Example 3: a recursive version of the algorithm that finds the number of digits in the binary
representation of a decimal number.
ALGORITHM BinRec(n)
//Input: A positive decimal integer n
//Output: The number of binary digits in n’s binary representation
if n = 1 return 1
else return BinRec(n/2) + 1
It is difficult to use the method of backward substitutions on values of n that are not powers of 2.
Therefore, the standard approach to solving such a recurrence is to solve it only for n = 2k .After
getting a solution for powers of 2, we can fine-tune this solution to get a formula valid for an
arbitrary n.
A(2k) = A(1) + k = k,
or, after returning to the original variable n = 2k and hence k = log2 n,
A(n) = log2 n ∈ (log n).
Example
The input size is given by the number of elements n; the basic operation is the key comparison
A[j ]<A[min]. The number of times it is executed depends only on the array size and is given by
the following sum:
CSE@HKBKCE 21
DAA Module-1
This is a sorting problem that compares adjacent elements of the list and exchange them if they
are out of order. By doing it repeatedly, we end up “bubbling up” the largest element to the
last position on the list. The next pass bubbles up the second largest element, and so on, until
after n − 1 passes the list is sorted.
Example: Sort -2 0 11 -9 45
CSE@HKBKCE 22
DAA Module-1
Given a string of n characters called the text and a string of m characters (m <= n) called the
pattern, find a substring of the text that matches the pattern. We want to find i-the index of the
leftmost character of the first matching substring in the text that matches. The search continues
until the entire text is exhausted. Last position in the text which can still be a beginning of a
matching substring is n-m. Beyond that position, there are not enough characters to match the
entire pattern; hence, the algorithm need not make any comparisons there.
ALGO
CSE@HKBKCE 23
DAA Module-1
Analysis
• In worst case the algorithm may have to make all m comparisons before shifting the pattern,
and this can happen for each of the n - m + 1 tries. Thus in worst case time complexity is
(nm)
• For a typical word search in a natural language text, however, most shifts would happen
after very few comparisons Therefore, the average-case efficiency should be considerably
better than the worst-case efficiency.
• For searching in random texts, it has been shown to be linear, i.e., (n + m) = (n)
CSE@HKBKCE 24