Daa Unit I
Daa Unit I
Algorithm, Performance Analysis-Space complexity, Time complexity, Asymptotic Notation- Big oh notation,
Omega notation, Theta notation and Little oh notation.
Divide and conquer: General method, applications-binary search, quick sort, merge sort, Strassen’s matrix
multiplication.
ALGORITHM:
Algorithm was first time proposed a purshian mathematician Al-Chwarizmi in 825 AD.
According to web star dictionary, algorithm is a special method to represent the procedure to
solve given problem.
OR
An Algorithm is any well-defined computational procedure that takes some value or set of
values as Input and produces a set of values or some value as output. Thus algorithm is a
sequence of computational steps that transforms the input into the output.
Formal Definition:
While Loop:
repeat-until:
repeat{
<statement-1>
….
<statement-n>
}until<condition>
8. A conditional statement has the following forms.
(1) If <condition> then <statement>
Else <statement-2>
Case statement:
Case
{ :<condition-1>:<statement-1>
….
:<condition-n>:<statement-n>
:else:<statement-n+1>
}
9. Input and output are done using the instructions read & write.
10. There is only one type of procedure:
Algorithm, the heading takes the form,
As an example, the following algorithm fields & returns the maximum of ‘n’ given
numbers:
Algorithm Max(A,n)
// A is an array of size n
{
Result := A[1];
for I:= 2 to n do
if A[I] > Result then
return Result;
}
In this algorithm (named Max), A & n are procedure parameters. Result & I are
Local variables.
Performance Analysis:
There are many Criteria to judge an algorithm.
– Is it correct?
– Is it readable?
– How it works
Performance evaluation can be divided into two major phases.
Space Complexity:
Example Program 3:
Iterative function for sum a list of numbers:
In the above example list[] is dependent on n. Hence S P(I)=n. The remaining variables
are i,n, tempsum each requires one location.
Example Program 4:
Algorithm int sum(int a[],int n)
{
int r=0;
for(int i=0;i<=n;i++)
{
r=r+a[i];
}
return r;
}
In the above example a[] is dependent on i. Hence SP(I)=n. The remaining variablesare
i, n, r, return r each requires one location.
If (n<=0) then
return 0.0
else
return rsum(list, n-1) + list[n];
}
In the above example the recursion stack space includes space for formal parameters, local variables
and return address. Each call to rsum requires 3 locations i.e for list[],n and return address. As the
length of recursion is n+1.
So S(P)>=3(n+1)
Time complexity:
T(P)=C+TP(I)
II Tabular method.
Total 2n+3
Example: 2
Statement s/e Frequency Total steps
Algorithm sum( x, n) 0 - 0
{ 0 - 0
total := 0; 1 1 1
for i := 1 to n do 1 n+1 n+1
{ 0 - 0
total:= total + i; 1 n n
} 0 - 0
Total 2n+2
Example: 3
Statement s/e Frequency Total steps
Algorithm add(a,b,c,n) 0 - 0
{ 0 - 0
for i:=1 to n do 1 n+1 n+1
for j:=1 to n do 1 n(n+1) n2+n
c[i,j]:=a[i,j]+b[i,j]; 1 n*n n2
} 0 - 0
Total 2n2+2n+1
Example:4
Statement s/e Frequency Total steps
Algorithm add(a,b,c,m,n) 0 - 0
{ 0 - 0
for i:=1 to m do 1 m+1 m+1
for j:=1 to n do 1 m(n+1) mn+m
c[i,j]:=a[i,j]+b[i,j]; 1 mn mn
} 0 - 0
Total 2mn+2m+1
Complexity of Algorithms:
The complexity of an algorithm M is the function f(n) which gives the running time and/or
storage space requirement of the algorithm in terms of the size ‘n’ of the input data. Mostly,
the storage space required by an algorithm is simply a multiple of the data size ‘n’.
Complexity shall refer to the running time of the algorithm.
The function f(n), gives the running time of an algorithm, depends not only on the size ‘n’
of the input data but also on the data. The complexity function f(n) for certain cases is:
1. Best Case : The minimum possible value of f(n) is called the best-case.
3. Worst Case : The maximum value of f(n) for any key possible input.
The field of computer science, which studies efficiency of algorithms, is known as analysis
of algorithms.
Algorithms can be evaluated by a variety of criteria. Most often we shall be interested in
the rate of growth of the time or space required to solve larger and larger instances of a
problem. We will associate with the problem an integer, called the size of the problem,
which is a measure of the quantity of input data, Rate of Growth.
The following notations are commonly use notations in performance analysis and used to
characterize the complexity of an algorithm:
Asymptotic notation:
Asymptotic notations are the mathematical tools that describe the behaviour of the algorithm and
determine the rate of growth of a function.
Rate of Growth: It is the rate at which the running time of algorithm grows as size of the input grows.
Big O Notation: Big O notation is used to measure the performance of any algorithm by
providing the order of growth of the function.
It gives the upper bound on a function by which we can make sure that the function will never
grow faster than this upper bound.
If f(n) and g(n) are the two functions , then
f(n)=O(g(n))
if there exists constants c and n0 such that f(n)<=c*g(n) for all n>= n0
Ex: 2
f(n)=4n+3 g(n)=n
Is f(n) =O(g(n))?
Ans: f(n)<=c*g(n)
4n+3<=c*n we must find suitable c value which satisfies equation.
For c=5, 4n+3<=5n, Now we must find suitable n0 value.
3<=5n-4n
n>=3
Yes, it is f(n)=O(g(n)) for all n>=3. f(n)grows linearly.
Ex: 3
f(n)=3n+2 g(n)=n
Is f(n) =O(g(n))?
Ans: f(n)<=c*g(n)
3n+2<=c*n we must find suitable c value which satisfies equation.
For c=4, 3n+2<=4n, Now we must find suitable n0 value.
2<=4n-3n
n>=2
Yes, it is f(n)=O(g(n)) for all n>=2. f(n)grows linearly.
Big Ω(Omega) Notation: Big Ω notation is used to measure the performance
of any algorithm by providing the order of growth of the function.
It gives the lower bound on a function by which we can make sure that the
function will never grow slower than this lower bound.
Ex: 2
f(n)=5n2 g(n)=n
Is f(n) =Ω(g(n))?
Ans: f(n)>=c*g(n)
5n2 >=c*n
5n>=c
for n0=1 c=5
Yes, it is f(n)=Ω(g(n))
Ex: 3
f(n)=5n2+2n-3 g(n)=n2
Is f(n) =Ω(g(n))?
Ans: f(n)>=c*g(n)
5n2+2n-3 >=c*n2
Here 2n-3 must be positive.
2n-3>=0
2n>=3
n>=3/2=2
for n0=2, c=5
Yes, it is f(n)=Ω(g(n))
Little oh: o
The function f(n)=o(g(n)) (read as “f of n is little oh of g of n”) iff
0<= f(n)<c.g(n)
for all c>0 and n>=n0
OR
Ex: 1
Is 3n+2=o(n2) ?
Ans: 3n+2< n2 for c=1 and n>=4
c=2 and n>=3
c=3 and n>=2 …..etc
Therefore 3n+2=o(n2)
Ex:2 Is 2n=o(n) ?
Therefore 2n≠o(n)
Ex:3 Is 2n=o(n2) ?
Therefore 2n=o(n2)
Ex:4 Is 2 n2=o(n2) ?
Therefore 2 n2≠o(n2)
Ex:5 Is 2 n2=o(n3) ?
Therefore 2 n2=o(n3)
Little Omega:ω
The function f(n)=ω (g(n)) (read as “f of n is little omega of g of n”) iff
OR
Ex: 1
Is n2 = ω (n) ?
Ans: c * n < n2 for c=1 and n>=2
c=2 and n>=3
c=3 and n>=4 …..etc
Therefore n2 = ω (n)
Ex: 2
Is n2 = ω (n) ?
Ans: c * n < n2 for c=1 and n>=2
c=2 and n>=3
c=3 and n>=4 …..etc
Therefore n2 = ω (n)
Ex: 3
Is n2/2 = ω (n) ?
Ans: c * n < n2 /2 for c=1 and n>=2
c=2 and n>=5
c=3 and n>=7 …..etc
Ex: 4
Is n2/2 = ω (n2) ?
Ans: c * n2 < n2 /2 for c=1 and n=1 condition fails
Analyzing Algorithms
Suppose ‘M’ is an algorithm, and suppose ‘n’ is the size of the input data. Clearly
the complexity f(n) of M increases as n increases. It is usually the rate of increase
of f(n) we want to examine. This is usually done by comparing f(n) with some
standard functions. The most common computing times are:
O(1), O(log2n), O(n), O(n. log2n), O(n2), O(n3), O(2n), n! and nn
Best case is the minimum number of steps that can be achieved for given parameters.
Ex: Consider five elements of any data structure in the order 7,17,27,37,47
In this our algorithm task is finding particular element present at which position.
CBest(n)=1
Worst case is the maximum number of steps that can be achieved for given parameters. And
also in case of failed, it checks the maximum number of steps.
CWorst(n)=n
CFailed(n)=n
Average case is the situation in which it is not either best case or worst case.
Element is found somewhere in the middle of the list.
DIVIDE AND CONQUER
General method:
Given a function to compute on ‘n’ inputs the divide-and-conquer strategy suggests
splittingthe inputs into ‘k’ distinct subsets, 1<k<=n, yielding ‘k’ sub problems.
These sub problems must be solved, and then a method must be found to
combine subsolutions into a solution of the whole.
If the sub problems are still relatively large, then the divide-and-conquer strategy can
possibly be reapplied. Often the sub problems resulting from a divide-and-conquer
design are of the same type as the original problem.
For those cases the re application of the divide- and-conquer principle is naturally
expressed by a recursive algorithm. DAndC(Algorithm) is initially invoked as
DandC(P), where ‘P’ is the problem to be solved. Small(P) is a Boolean- valued
function that determines whether the input size is small enough that the answer can
be computed without splitting. If this so, the function ‘S’ is invoked. Otherwise, the
problem P is divided into smaller sub problems. These sub problems P1, P2 …Pk
are solved by recursive application of DAndC. Combine is a function that determines
the solution to P using the solutions to the ‘k’ sub problems. If the size of ‘P’ is n and
the sizes of the ‘k’ sub problems are n1, n2 ….nk, respectively, then the computing
time of DAndC is described by the recurrence relation.
T(n)= { g(n) n small
T(n1)+T(n2)+……………+T(nk)+f(n); otherwise.
Where T(n) is the time for DAndC on any input of size ‘n’.
g(n) is the time of compute the answer directly for small inputs. f(n) is the time for dividing P
& combining the solution to sub problems.
Algorithm DAndC(P)
{
if small(P) then return S(P);
else
{
divide P into smaller instances
P1, P2… Pk, k>=1;
Apply DAndC to each of these sub problems;
return combine (DAndC(P1), DAndC(P2),…….,DAndC(Pk));
}
}
The complexity of many divide-and-conquer algorithms is given by recurrence relationof the
form
T(n) = T(1) n=1
=aT(n/b)+f(n) n>1
Where a & b are known constants.
We assume that T(1) is known & ‘n’ is a power of b (i.e., n=bk)
One of the methods for solving any such recurrence relation is called the substitution
method. This method repeatedly makes substitution for each occurrence of the
function. T is the right-hand side until all such occurrences disappear.
Example: 1
Consider the case in which a=2 and b=2. Let T(1)=1 & f(n)=n. We have,
T(n) = 2T(n/2)+n
= 2[2T(n/2/2)+n/2]+n
=[4T(n/4)+n]+n
= 4T(n/4)+2n
= 4[2T(n/4/2)+n/4]+2n
= 4[2T(n/8)+n/4]+2n
= 8T(n/8)+n+2n
= 8T(n/8)+3n
*
*
OR
T(n) = 2T(n/2)+n
= 2[2T(n/2/2)+n/2]+n
=[4T(n/4)+n]+n
= 4T(n/4)+2n
= 4[2T(n/4/2)+n/4]+2n
= 4[2T(n/8)+n/4]+2n
= 8T(n/8)+n+2n
= 8T(n/8)+3n
*
*
=n T(n/n)+k n
T(n) = n T(1)+k n
T(n) = logn n
Therefore T(n) = n logn
O( n log n)
Example: 2
Consider the case in which a=1 and b=2. Let T(1)=1 & f(n)=c We have,
T(n) = T(n/2)+c
= [T(n/2/2)]+c+c
=[T(n/4)]+c+c
=[T(n/4/2)+c+c+c
=[T(n/8)]+3c
*
*
= T(n/n)+k c
= T(1)+k c
T(n) = log n * c
O( log n)
BINARY SEARCH
ITERATIVE METHOD:
Example: Search the key values 42, 55 and 30 from the list
3, 6,8,12,14,17,25,29,31,36,42,47,53,55,62
Ans:
Key Value = 42
3 6 8 12 14 17 25 29 31 36 42 47 53 55 62
Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Search is Successful
Key Value=55
3 6 8 12 14 17 25 29 31 36 42 47 53 55 62
Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Search is Successful
Key Value = 30
3 6 8 12 14 17 25 29 31 36 42 47 53 55 62
Index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Search is Unsuccessful
1 3 5 7 9 11 13 15
Algorithm BinaySearch(A,n,key)
{
low=l; high=n;
while(low<=high)
{
mid=(low+high)/2;
if (key= =A[mid])
return mid;
if (key < A[mid])
high = mid-1;
else
low = mid +1;
}
return 0;
}
Algorithm RBinaySearch(low,high,key)
{
if (low = = high)
{
if (A[low]= = key)
return low;
else
return 0;
}
else
{
mid=(low+high)/2;
if (key = = A[mid])
return mid;
if (key < A[mid])
return RBinarySearch(low,mid-1,key);
else
return RBinarySearch(mid+1,high,key);
}
}
For the list of elements of size of n, based on the mid value, each time we are considering n/2
part of the list. Therefore, the complexity of Binary search is T(n)=T(n/2)+c which is in the
form of T(n)=a T(n/b)+f(n) where a=1, b=2 and f(n)=c
Hence O(log n)
QUICK SORT
The quick sort algorithm partitions the original array by rearranging it into two groups. The
first group contains those elements less than some arbitrary chosen value taken from the set,
and the second group contains those elements greater than or equal to the chosen value.
The chosen value is known as the pivot element. Once the array has been rearranged in this
way with respect to the pivot, the very same partitioning is recursively applied to each of the
two subsets. When all the subsets have been partitioned and rearranged, the original array is
sorted.
Procedure:
Select first element as the pivot element. Move ‘i’ pointer from left to right in search of an
element larger than pivot. (As long as i<pivot, increment i) and move the ‘j’ pointer from
right to left in search of an element smaller than pivot (As long as j>p, decrement j). If such
elements are found, the elements are swapped. This process continues till the ‘i’ pointer
crosses the ‘j’ pointer. If ‘i’ pointer crosses ‘j’ pointer, the position for pivot is found and
interchange pivot and element at ‘j’ position.
Let us consider the following example with 7 elements to analyze quicksort
50 15 25 49 5 10 16
1 2 3 4 5 6 7 Remarks
50 15 25 49 5 10 16
Pivot i J Initial set up
Pivot J We do not find i which is greater than pivot
element. So swap j and pivot element
16 15 25 49 5 10 50 50 is in the correct position
Pivot i j Again find i>pivot and j<pivot
i j Swap i and j
16 15 10 49 5 25 50
Pivot i j Again find i>pivot and j<pivot
16 15 10 49 5 25 50
Pivot i j Swap i and j
16 15 10 5 49 25 50
Pivot i j Again find i>pivot and j<pivot
16 15 10 5 49 25 50
Pivot j i i and j are overlapped. So swap j and pivot
element
5 15 10 16 49 25 50
Pivot i j 16 is in the correct position.
We do not find element j less than pivot
5 15 10 16 49 25 50 5 is in the correct position
Pivot i,j j is less than pivot, swap j and pivot
5 10 15 16 49 25 50 10 and 15 are in the correct position
pivot i,j j is less than pivot, swap j and pivot
5 10 15 16 25 49 50 List is sorted
Quicksort Algorithm:
Quicksort(A,i,j)
{
if ( i < j)
{
Ploc = Partition(A,i,j);
Quicksort(A,i, Ploc – 1);
Quicksort(A,Ploc + 1,j);
}
}
Partition Algorithm
Partition(A,i,j)
{
Pivot = A[i];
i=1;
j=n;
while(i<n)
{
while(A[i]<=pivot)
{
i++;
}
while(A[j]>pivot)
{
j--;
}
if(i<j)
{
Swap(A[i],A[j]);
}
else
Swap(A[pivot],A[j]);
return j;
}
Complexity of Quick Sort:
Worst Case:
x
Pivot --------------------------------------- n-1---------------------------------------------------
Let us suppose that x is the smallest element then no elements less than x
Again, let us suppose that list is already in sorted order,
x Y
Pivot --------------------------------------- n-2----------------------------------------------
x Y z
Pivot ----------------------------------n-3----------------------------------------------
So Time complexity is
T(n)=T(0)+T(n-1)+n
=T(n-1)+ n
=T(n-1-1)+(n-1)
=T(n-2)+(n-1) + n
=T(n-2-1)+ (n-2) + n-1 + n
=T(n-3)+(n-2) + n-1 +n
*
*
*
= T(n-k) + (n-(k-1)) + …..+ (n-2)+(n-1)+n
MERGE SORT
Merge sort algorithm is a classic example of divide and conquer. To sort an array, recursively,
sort its left and right halves separately and then merge them.
This strategy is so simple, and so efficient but the problem here is that there seems to be no
easy way to merge two adjacent sorted arrays together in place (The result must be built up in
a separate array). The fundamental operation in this algorithm is merging two sorted lists.
Because the lists are sorted, this can be done in one pass through the input, if the output is put
in a third list.
Example: 415 213 700 515 712 715
515 712
415 213
213 415
515 712
Compare i and j, as long as i<j add i to output list or add j to output list. If i>mid then add all
remaining j values to output list. Similarly, if j>high then add all remaining i values to output
list.
Therefore, final sorted list is 415 213 700 515 712 715
*
*
The matrix multiplication of algorithm due to Strassen is the most dramatic example of divide
and conquer technique.
Let A and B be two n×n Matrices. The product matrix C=AB is also a n×n matrix whose i,
jth element is formed by taking elements in the ith row of A and jth column of B and
multiplying them to get
The usual way C(i, j)=∑1≤𝑘≤𝑛 𝐴(i, 𝑘)𝐵(𝑘, j) --------- Eqn 1
Here 1≤ i & j ≤ n means i and j are in between 1 and n.
To compute C(i, j) using this formula, we need n multiplications.
The divide and conquer strategy suggest another way to compute the product of two n×n
matrices. For Simplicity assume n is a power of 2 that is n=2k, k is a nonnegative integer.
If n is not power of two then enough rows and columns of zeros can be added to both A and
B, so that resulting dimensions are a power of two.
To multiply two n x n matrices A and B, yielding result matrix ‘C’ as follows:
Let A and B be two n×n Matrices. Imagine that A & B are each partitioned into four square
sub matrices. Each sub matrix having dimensions n/2×n/2.
The product of AB can be computed by using Eqn 1 formula.
If AB is product of 2×2 matrices then
= 72T(2k-2)
= ------------
= ------------
= 7iT(2k–i)
Put i =k
= 7kT(20)
As k is the power of 2
n
That is T(n) = 7log2
= log
n 2
= O(nlog 7)= O(n2.81)
So, concluding that Strassen’s algorithm is asymptotically more efficient than the standard
algorithm.
Strassen’s Matrix Multiplication Algorithm:
Algorithm MatricMultiplication(A,B,n)
{
if(n<=2)
{
c11= a11 b11 + a12 b21;
c12= a11 b12 + a12 b22;
c21= a21 b11 + a22 b21;
c22= a21 b12 + a22 b22;
else
{
mid=n/2;
MM(A11,B11,n/2)+MM(A12,B21,n/2);
MM(A11,B12,n/2)+MM(A12,B22,n/2);
MM(A21,B11,n/2)+MM(A22,B21,n/2);
MM(A21,B12,n/2)+MM(A22,B22,n/2);
}
}
A= 1 3 B= 6 8
7 5 4 2
C21 C22
P = (1 + 5) (6 + 2) = 48
Q = 6(7 + 5) = 72
R = 1 (8 -2) = 6
S = 5(4 - 6) = -10
T = 2(1 + 3) = 8
U = (6 + 8) (7 – 1) = 84
V = (4 + 2) (3 – 5) = -12
C11 = 48 + (-10) – 8 +(-12) = 18
C12 = 6+ 8 =14
C21 = 72 + (-10) = 62
C22 = 48 + 6 – 72 +84 = 66
Therefore C =
18 14
62 66
66
UNIT-I IMP QUESTIONS
1) Show that the following equalities are correct:
a) 5n2 - 6n = θ (n2)
b) n! = O(nn)
c) 2n22n + n log n = θ (n22n)
d) n3 + 106n2 = θ (n3) (4+4+4+3) M
2) What are asymptotic notations? Explain with examples. Write and explain quick sort
algorithm with an example. (8+7) M
3) a) Write and explain randomized quick sort algorithm.
b) Discuss about Big oh O, Omega Ω and Theta θ notations with examples. (8+7) M
4) a) Using Merge sort, sort the following elements:
310, 285, 179, 652, 351, 423, 861, 254, 450, 520
b) Analyze the computing time complexity of binary search algorithm. (7+8) M
5) a) Discuss in detail various notations used for expressing the time complexity
of algorithms, with examples.
b) What is Performance Analysis? Explain Space Complexity and Time Complexity with
examples. (7+8) M
6) a) Explain the process of merge sort by a list of any 11 integers (distributed
randomly). Write the algorithm and analyze its time complexity.
b) Write an algorithm to find matrix multiplication using Strassen’s. (8+7) M
7) What is an algorithm? 2M
8) Define static space tree. 2M
9) a) Write and explain the general method of divide-and-conquer strategy.
b) Derive the time complexity of Strassen’s matrix multiplication. (5+5) M
10) a) Write and explain recursive algorithm of binary search method.
b) What is space complexity? Explain with suitable examples. (5+5) M