Design and Analysis of Algorithms Chapter 1 1.1 What is an Algorithm? Def: An algorithm is a sequence of unambiguous instructions for solving a problem, i.e., for obtaining a required output for any legitimate input in a finite amount of time. The following points are important in designing an Algorithm. 1. The unambiguity requirement for each step of the algorithm cannot be compromised. 2. The range of inputs for which an algorithm works has to be specified carefully. 3. The same algorithm can be represented in several different ways. 4. There may exist several algorithms for solving the same problem. 5. Algorithms for the same problem can be based on very different ideas and can solve the problem with dramatically different speeds. Recall The Greatest Common Divisor Problem Definition: Let a and b be integers, not both zeros. The largest integer d such that d|a and d|b is called the greatest common divisor of a and b, and it is denoted by gcd(a,b). Where the gcd(a,0)=a (gcd(0,b)=b Note: The symbol d|a is read as "d divides a." and it means that d divides a without remainder. i.e a mod d =0 or a/d=c, where c is an integer. There are several methods to find the gcd(a,b) - Euclidian's Algorithm - By definition - Sorting out the common divisors - Prime Factorization Method 1: The Euclidean Algorithm Theorem: Let a=bq+r, where a, b, q, and r are integers. Then gcd(a,b)=gcd(b,r). Why? (proof) Let d=gcd(a,b) Then by def, we have d|a and d|b From Number theory we know that: if an integer d divides two integers a and b then it also divides any linear combination of a and b. Therefore, a linear combination of a and b that we have is (a-bq), therefore, If d|a and d|b then d|(a-bq) But, a-bq=r Therefore, d|r Now we have d|b and d|r, then d is gcd(b,r), but d=gcd(a,b) Then gcd(a,b)=gcd(b,r) Which means, instead of finding the gcd(a,b), we find the gcd(b,r) and so on we keep reducing the integers until we reach r=0. When r=0, gcd(b,r)=b Ex: find gcd(27,366) by Euclidian's Algorithm. Solution 366=27(13)+15 27=15(1)+12 15=12(1)+3 12=3(4)+0 →gcd(3,0)=3 Or we can say: the gcd(366,27) is the last non-zero remainder. That is gcd(366,27)=3 The Algorithm: [Euclidian's] S1 Input a,b, with a>b S2 if b=0 then return a as gcd(a,b) S3 If b≠0 then compute r=a mod b S4 Set a=b and b=r then go to S2 Method 2: [By Definition] This method is based on the definition where the greatest common divisor of a and b is the largest integer that divides both a and b Note: Since gcd(a,b) divides both a and b, the gcd(a,b)<a and gcd(a,b)<b. Let d=gcd(a,b) with a>b. therefore, it is also possible that gcd(a,b)=b. First thing we do is to set d=min(a,b). Then we check if d divides a and b. if it does then d is outcome. If it does not, then we reduce d by 1 and try again. Ex: Find gcd(18,60) 60>18 → gcd(60,18)=d → d=min(60,18)=18 Check: if 18|60 no and 18|18 yes → d=18-1 17|60 no and 17|18 no → d=17-1 … d=7-1 6|60 yes and 6|18 yes Then d=6 is the gcd(60,18) The algorithm: [by def] S1 Input a, b with a>b S2 set d=min{a,b} S3 if a mod d=0 then go to S4, otherwise go to S5 S4 if b mod d=0 then go to S6, otherwise go to S5 S5 d=d-1 go to S3 S6 return d=gcd(a,b) Note: There is a way to improve the algorithm by combining S3 and S4 into one step by using the logical operation AND Note: unlike Euclidian's algorithm, this algorithm will fail if one of the integers is zero. It means the algorithm here is not specific. Method 3: Listing The divisors of a and b This method also depends on the definition. But it depends more on following the definition literally. Ex: find gcd(60,18) by listing the divisors Ans: 60: 1,2,3,4,5,6,10,12,15,20,30,60 18: 1,2,3,6,9,18 The largest common divisor is 6 so d=6 is the gcd(60,18) The algorithm: [by listing the divisors] S1 find the divisors of a and name them as a1, a2, …, an S2 find the divisors of b and name them as b1, b2, …, bn S3 Sort out the common divisors that are found in S1 and S2 and name them as d1, d2, …, dk S4 d=max{d1, d2, …, dk}, d=gcd(a,b) The problem with this algorithm is in the first two steps. Finding divisors of an integer usually takes time, especially if the integer is large. The fastest way to find all the divisors is by starting with the number itself and dividing it by itself, then reducing it by 1 and start again.