DAA - Ch. 1 (Lecture Notes)
DAA - Ch. 1 (Lecture Notes)
DAA - Ch. 1 (Lecture Notes)
Notes Unit-1
Algorithm:
The word algorithm comes from the name of a Persian mathematician Abu Ja’far
Mohammed ibn-i Musa al Khowarizmi.
In computer science, algorithm refers to a special method useable by a computer for solution
of a problem.
An algorithm takes some value or set of values, as input and produces some value, or
set of values, as output.
Characteristics of algorithms
Input: If an algorithm takes inputs, it should be well-defined inputs. What the algorithm
takes in as input, Zero or more quantities supplied.
Output: The algorithm must clearly define what output will be produced and it should be
well-defined. At least one quantity is produced as an output.
Definiteness: All the steps in the algorithm should be defined precisely. Each instruction
should be cleared and unambiguous.
Finiteness: All the steps required in the algorithm should be finite, If we trace out the
instructions of an algorithm, then for all cases, the algorithm terminates after a finite
number of steps. it should not end up in infinite loops.
Effectiveness: each step in the algorithm must be able to be performed in a finite amount of
time. Every instruction must be basic so that it can be carried out in principal by a person
using only pen and pencil.
Non –ambiguous: more than one interpretation should not be generated for single step.
Correctness: Algorithm should produce an appropriate and correct output for each input
produce.
Efficient: Algorithm should run as quickly as possible, and use as little memory as possible.
Figure 1 Characteristics of an algorithm
More than one algorithm is possible for the same application. For example, we know that
numbers can be sorted using different algorithms. Number of comparisons performed by
one algorithm may vary with others for the same input. Hence, time complexity of those
algorithms may change. At same time, we need to calculate the memory space required by
each algorithm.
Time & Space analysis are of crucial importance for performance measurement of a
software module.
Order of Growth
Any algorithm is expected to work fast for any input size. For smaller input size any
algorithm will work fine but for higher input size the execution time is much higher.
By increasing the size of input size (n) we can analyze how well our algorithm works. Let
input size, n=5 and we have to sort the list of elements for e.g. 5,9,50,35,2 So for n=5 our
algorithm will work fine but what if n=10000?
So how the behaviour of algorithm changes with the no. of inputs will give the analysis of
the algorithm and it is called as Order of Growth.
Rate of Growth
The rate at which the running time increases as a function of input is called rate of growth.
The best, worst and average cases of an algorithm express what the resource usage is at
least, at most and on average, respectively.
The resource being considered is running time, but it could be memory or the other
resource
1)Best case
The best case complexity of the algorithm is the function defined by the minimum number
of steps taken on any instance of size n.
Best case is a lower bound on the running time for any input.Minimum time required for
program execution is known as best case.
Best case of an algorithm gives guarantee that the algorithm will take minimum this
amount of time.
2)Average case
The average case is a function defined by the average number of steps taken on any
instance of size n. Average time required for program execution is known as average case
for algorithm.
Average case is a tight bound on the running time for any input.
3)Worst case
The worst case complexity of the algorithm is the function defined by the maximum number
of steps taken on any instance of size n.
Worst case is a upper bound on the running time for any input.Maximum time required for
program execution is known as best case.
Worst case of an algorithm gives guarantee that the algorithm will take maximum this
amount of time.
Asymptotic Complexity
Asymptotic notation gives running time of an algorithm as a function of input size n for large
n.Asymptotic Complexity expressed using only the highest-order term in the expression for
the exact running time. Instead of exact running time, say Q(n2).
The notations describe rate-of-growth relations between the defining function and the
defined set of functions.Asymptotic Complexity describes behavior of function in the limit.
The word Asymptotic means approaching a value or curve arbitrarily closely (i.e., as some
sort of limit is taken).
The only difference being, here we do not have to find the value of any expression where n
is approaching any finite number or infinity, but in case of Asymptotic notations, we use the
same model to ignore the constant factors and insignificant parts of an expression, to
device a better way of representing complexities of algorithms, in a single coefficient, so
that comparison between algorithms can be done easily.[1]
Now, as per asymptotic notations, we should just worry about how the function will grow as
the value of n(input) will grow, and that will entirely depend on n2 for the Expression 1, and
on n3 for Expression 2. Hence, we can clearly say that the algorithm for which running time
is represented by the Expression 2, will grow faster than the other one, simply by analyzing
the highest power coefficient and ignoring the other constants(20 in 20n2) and insignificant
parts of the expression(30n - 4 and 10n - 2).
The main idea behind casting aside the less important part is to make things manageable.
All we need to do is, first analyze the algorithm to find out an expression to define it's time
requirements and then analyze how that expression will grow as the input(n) will grow.
Ο Notation
f(n)=O(g(n)) implies: Ο(g(n)) = { f(n) : there exists positive constants c>0 and n0 such that
f(n) ≤ c.g(n) for all n > n0. } [2]
The question is why we need big-O complexity representation when we already have the
big-Θ notation, which represents the tightly bound running time for any algorithm. Let's
take a small example to understand this.
Consider Linear Search algorithm, in which we traverse an array elements, one by one to
search a given number. [1]
In Worst case, starting from the start position of the array, we find the element or number
we are searching for at the end, that lead to a time complexity of n, where n represents the
number of total elements.
But it can happen that the element that we are searching for is the first element of the
array, in that case the time complexity will be 1.
Now in this case, saying that the big-Θ or tight bound time complexity for Linear search is
Θ(n).It means that the time required will always be related to n, as this is the right way to
represent the average time complexity, but when we use the big-O notation, we mean to
say that the time complexity is O(n), which means that the time complexity will never
exceed n, defining the upper bound, hence saying that it can be less than or equal to n,
which is the correct representation.[1]
This is the reason, most of the time you will see Big-O notation being used to represent the
time complexity of any algorithm, because it makes more sense.
Ω Notation
f(n)= (g(n)) implies: (g(n)) = { f(n) : there exists positive constants c>0 and n0 such that
f(n) ≥ g(n) for all n > n0. } [2]
θ Notation
θ notation express as both the lower bound and the upper bound or tighter bound of an
algorithm.
f(n)= (g(n)) implies: (g(n)) = { f(n) : there exists positive constants c1>0, c2>0 and n0 such
that c1.g(n) ≤ f(n) ≤ c2.g(n) for all n > n0. } [2]
OR, if & only if f(n)=O(g(n)) and f(n)= (g(n)) for all n > n0
For example, if time complexity for some algorithm is represented by the expression 10n2 +
2n, and we use the Big-Θ notation to represent this, then the time complexity would be
Θ(n2), ignoring the constant coefficient and removing the insignificant part, which is 2n.
Properties of Asymptotic Notations[2]:
1. General Properties :
If f(n) is O(g(n)) then a*f(n) is also O(g(n)) ; where a is a constant.(1)
Example: f(n) = n²+5 is O(n²)
then 7*f(n) = 7(n²+5)
= 7n²+35 is also O(n²)
This property also property satisfies for both Θ and Ω notation.
Solution:
Solution:
Solution:
Solution:
Solution:
Solution:
Solution:
Solution:
Space Complexity:
Recurrence relations:
• Refer as an equation that recursively defines a sequence where the next term
is a function of the previous terms
• Can easily describe the runtime of recursive algorithms.
The base case(termination condition) is reached when n == 0. The method performs
one comparison. Thus, the number of operations when n == 0, T(0), is some
constant c.
Base Case: T(n)=c , for n=0 (Here T(n) is running time and n is input size)
I. Substitution Method
II. Iterative Method
III. Recurrence Tree Method
IV. Master’s Method
T(n)=T(n-1)+1 ...........................1)
T(n-1)=T(n-2)+1 ..........................2)
T(n-2)=T(n-3)+1 .........................3)
T(n)=T(n-3)+3
T(n)=T(n-k)+k
T(n)=T(n-n)+n
T(n)=1+n
so ,T(n)=O(n)
Solution:
T(n)=T(n-1)+n ......................1)
T(n-1)=T(n-2)+(n-1)
T(n-2)=T(n-3)+(n-2)
T(n)=T(n-2)+(n-1)+n
T(n)=T(n-3)+(n-2)+(n-1)+n .......................2)
continue for k times .now equation look like,
T(n)=T(n-(k+1))+(n-k)+.......(n-2)+(n-1)+n .....................3)
T(n)=T(n-(n-2+1))+(n-(n-2))+.......(n-2)+(n-1)+n
T(n)=T(1)+2+.......(n-2)+(n-1)+n
T(n)=1+2+.......(n-2)+(n-1)+n
T(n)=(n(n+1))/2
So T(n)=O(n2)
References :
[1] https://www.studytonight.com/data-structures/aysmptotic-notations
[2]https://www.geeksforgeeks.org/analysis-of-algorithms-set-3asymptotic-notations/
Chapter: 1 Introduction
In some of the cases substitute method is hard to apply and therefore require having
easy way to guess the solution of recurrence equation. Recurrence Tree method is a
graphical tree based approach to solve recurrence problems. It is basically divide and
concur based approach where the problem is sub divided in to small sub problems and
then at each level of Tree the cost is sum up which is known as pre-level cost. At last all
pre-level cost is summed up to have final cost.
It provide good guess for the solution which can be then verified with the help of
substitution method. Let’s understand the process by taking examples.
In above example T(n) is sub divided into three parts each of T(n/4) and then each sub
problem will be divided into further sub problem as shown in below figure. We continue
expanding each node in the tree by breaking it into its constituent parts as determined
by the recurrence.
Let’s take advantage of small amounts of sloppiness and use an infinite decreasing
geometric series as an upper bound.
Thus, we have derived a guess of T (n) = O(n2).Now let’s verify it with substitution
method.
It’s a cook book method for solving the recurrence of the given form,
T(n)=a(n/b) +f(n)
Where a>=1 and b >1 and f(n) is asymptotic positive function of n.here the problem is
divided in to a sub problems with size of (n/b).After solve the sub problems the cost is
added to have final cost. So final f(n)=D(n)+C(n).
Master’s Theorem.
For given recurrence T(n)=a(n/b) +f(n), there are following possible cases.
• In recurrence tree method, we calculate total work done. If the work done at
leaves is polynomially more, then leaves are the dominant part, and our result
becomes the work done at leaves (Case 1).
• If work done at leaves and root(f(n)) is asymptotically same, then our result
becomes height multiplied by work done at any level (Case 2).
• If work done at root(f(n)) is asymptotically more, then our result becomes work
done at root (Case 3).
Case 2:
we can apply case 2 of the master theorem and conclude that the solution is T (n)
= Θ(log n).
Case 3:
Let’s take T(n) = 3T(n/4) + n lg n.
we have a = 3, b = 4, f (n) = n lg n, and Θ(nLogba)= Θ(n0.793) . Since f(n)= Θ(n0.793+c)
Where c=0.217
Even though it has the proper form: a=2,b=2,f(n)=n lg n, and n logba =n,Now f(n)=n lg n
which is greater than nlogba =n. This is actually not a polynomially larger. That is the
ration is (n lg n)/n=lg n is asymptotically less that nc for any c
So actually this is not case 2 or case 3 but this case fall between case 2 and case
3.So master method can not apply here.