09:22:18 >>Professor: good morning everyone. We will get started in just a minute. All right hi everybody. A couple of announcements before we dive in here. First of all, on the wait list, sorry for the delay on that. I appreciate those of you on the wait list have to decide whether to start working on home work one. We will make final the enrollment this evening. I hope we will add twenty or so students. If so I will send permission codes tonight. 09:22:54 If you don't get an email from me to night you can assume you didn't make the course. Unfortunately, we can't fit everyone from the wait list. I hope to fit a few more. Keep an eye out for the email tonight. If you get in then you can get going on home work one. Other wise, hopefully, you can get in to the class next quarter. Other announcement is that there's no class on Monday. Monday is Martin Luther king day. I will hold office hours. 09:23:37 If you have questions about anything, but we will not have lecture. We will have sections or rather office hours of our TA's as usual on Tuesday which is when the home work is due. Last time we had introduced the master theorem for divide and conquer recurrences. The idea of this theorem was it gives you a cookie cutter approach to solve any recurrence of this general form were your saying the run time of some algorithm on problems of size N, 09:24:17 Is given by some constant times the run time of the algorithm on some fraction of the original input size. You had a problem of size N now we are dividing it by some B greater than one plus another term a nonrecursive term F of N. The theorem says if these values A, B, and your choice of function F here fit in to any of these three cases then you can just read off directly what the asymptotic solution of the recurrence is. 09:24:59 If F or N grows slowly enough with respect to the input size N basically there's this critical exponent C which is the log based B of A where B and A are these constants in the recurrence. If F of N grows slowly enough compared to N to the C then N to the C which is basically the amount of work done by the recursive calls dominates so you get the solution being theta of N to the C. If the growth rate of F is exactly N to the C then you end up having the over all solution be, 09:25:49 N to the C plus a log factor. N to the C types log N. If is grows more quickly and satisfies this tech condition which is satisfied by most functions anything that's polynomial will satisfy this condition. The F of N dominates and so the over all solution to the recurrence is theta of F of N. Last time we saw a couple of examples of applying this theorem in the in first example we have (Reads board).. We are dividing the problem in to nine subproblems. 09:26:32 Each of which is the third of the size of the original problem. We are doing a linear amount of extra work. Then we first compute this exponent C. It's the log based three of N in this case which is two. Now we know that we are in case one because if we look case one here we check is F of NO of N to the C for some ep salon. Is this term N (INDISCERNIBLE). It is because N is linear. We could have ep salon be point one. 09:27:15 Or some small value. This is N to the one point nine and N to the one is O of (INDISCERNIBLE). Case one applies. We can read off the answer as T of N is theta -- sorry theta of N squared. N to the C. Oh, thank you. I forgot to start the recording. Let me start it now. Thank you for pointing that out. If you watch the recording I started this late. I was recapping the master theorem for recurrences. I made the announcement we will 09:27:50 Make final the wait list to night. Look for an email with permission codes. I hope to let in twenty or so students from the wait list. If you don't get an email from me tonight you can assume you didn't make it in the course. There's no class Monday because it's a holiday but I have office hours. We can plug in to the master theorem A and B and compute C. We check C applies. We can read off the answers as theta then squared. 09:28:43 In the other example here now we have different values of A and B. Someone pointed out in the questions last time I misstated the log here. It's log base B of A. B is the factor that you divide N by. In this example we are multiplying N by two thirds. That's like dividing it by three halves. The base of the log rhythm is three halfs. We take A which is just one. We have the log based three halves of one which is zero. Log of one to any base is zero. N to the C here is N to the zero whi 09:29:29 Which is just one. Our nonrecursive term is also of order theta of one. We are in case two where F of N is theta of N to the C. The answer is theta of N to the C log N. N to the C is one because C is zero times log N so we get T of N is theta of log N. Let's do an example of case three. I will leave case three up here. A question here. When you use the master theorem should you had specify what values ep salon can take on? 09:30:11 Yes you should say one value of ep salon that works. You have to verify this that holds. (Reads board).. You should give some value of ep salon that makes this work. You don't have to say what all possible values are. It would be good to write that. I didn't bother doing it here. Let me be more explicit in our case three example so we can see how to do that. Let's look at the following recurrence. Suppose we had (Writing on board). 09:30:56 Here's our recurrence. The first thing to do is compute the critical exponent C. That is going to be the log base four in this case because we are dividing by four here. Log base four of three. The number of sub problems. This is not some nice number. This is a number we can work out what it is. It's going to be less than -- it's certainly less than one. If you think of what power you have to raise four to to get three, well four to the one is four. 09:31:42 You have to raise four to something less than one to get three. I have not worked out what this is. It's certainly less than one. If we look at our cases here. We are not going to be in either case one or two. Because N to the C is going to be N to the something less than one. Where as our F of N here is N squared. We are not in cases one or two for sure. Let's check if case three applies. We have F of F is N squared. The question is, is it omega of N to the C plus ep salon 09:32:31 For some ep salon of zero. Yes it is. C is less than one. This is two. We could take ep salon to be one. If we put that to be one then N to the C plus one is less than two. Because C is less than one. N squared will be omega of N to the C plus one. This is a value of ep salon greater than zero such that this holds. So far so good. Now to check that case three holds or case three of the master theorem applies we have to check the second condition here. 09:33:21 For some D less than one and large N you have this inequality. Let's plug in to this inequality and see if it works out. A is three. F of N over B. F of N is N squared. That N over B is N over four. Now we are applying F to that. It's that squared. The question is this less than or equal to D times F of N? F of N being N squared for some D less than one. Let's simplify this a little bit. What do we have over here? If we just separate out the numerater and denominater here 09:33:58 We get four squared on the bottom which is sixteen. We have three sixteenths times N squared. We want this less than or equal to DN squared for some constant D which will work. What we can do is just set D to be three sixteenths. Then as required we will have that there's some D strictly less than one. This is strictly less than one. Now this left-hand side which is here will be less than or equal to the right-hand side. That can is also met. 09:34:51 We know case three applies. We can read off the answer. Oops. T of N. The answer according to case three of the theorem is it's just theta of F of N which is N squared. A good question coming in here. Can we see an example where the master theorem does not apply? Yes. Absolutely. If I cover up the three cases for a second here. One simple way that the master theorem could not apply is if the recurrence is not of this form. One example is what if instead of N divided 09:35:28 By a constant you have N divided by one. In the home work you see that. You can see recurrence for the f I b numbers in terms of the N minus one and two f I b numbers. You can't apply the master theorem. There's other cases that don't fit. This makes sense for algorithms were your dividing the problem in to A parts each of which has the same size N over B. If you had an algorithm that divided the problem in to differently sized parts, 09:36:04 You have a problem of size N and you divide it in to one part of size N over two and two parts of size N over four then the recurrence wouldn't be of this form and you can't apply the master theorem again. Finally, it's possible to have examples where the recurrence is of this form but none of these three cases apply where you fall in the cracks. There's gaps between these cases. They don't cover all possibilities. That's a little more complicated. 09:36:40 I will not give an example here. You can think can you cook up a function F of N that doesn't satisfy any of these three cases. It's possible to do that. This gives an example of how to apply the master theorem in all three cases. Basically, what you need to do is look at what the value of this exponent C is by plugging in A and B. Then you go through the three cases and check based on how quickly F grows which of the three cases are you in if any. 09:37:15 If any of them apply the theorem tells you this is the asymptotic solution. This is a very useful method for solving lots of recurrences because it saves you all the time of going through the recursion tree process we talked about before. To see how we are all doing on understanding this I want to give you a quick exercise to practice using the theorem. I will leave the theorem up for you here so you can see it. There it is. 09:39:47 Here's the poll. I'm giving a recurrence here. Think for a minute about what the answer would be according to the master theorem and then we will go over it. Okay. Let's go over this. It looks like we have answers from most of you. Great. Okay. Here are the results from everyone. You can see that more than half of you said N squared log N and you are right. You also said N squared. Let's go over this. 09:40:42 let's see why it's N squared log N. The other example that we saw was in this poll it was (Writing on board). The first thing we need to do is compute the value of this critical exponent, C. We have C is going to be the log. Now it's base B which is the divider here. Log base two of the constant in front which is four. Log base two of four is two. Because two squared is four. Now we need to compare the growth rate of F of N to N to the C. 09:41:26 Which is going to be N squared. This is of order N squared. Three N squared. That says we will be in case two of the theorem here. F of N is three N squared which is theta of N squared. Which is the same as theta of N to the C because C is two. We are in case two here. Case two applies. The solution according to the master theorem is N to the C log N. N to the C is N squared so we have N square log N which is what most of you said. 09:42:12 Any questions about how this worked? Okay. Great. This is all I'm going to say about the master theorem. As I mentioned, we will not prove it here. The proof is using the method of recursion trees and it's done in all the details in CLRS if you want to see how that works. Another thing I will mention since there was a question about instances where the master theorem does not apply. There are generalizations of this method 09:42:51 That work for other types of recurrences that this one doesn't cover. I will put a note in here in case any of you want to look this up. There's a very interesting generalization of the master theorem which I'm not expecting you to know about, but just if you are interested. That handles the case of differently sized subproblems. There's a generalization of the master theorem for differently sized subproblems. 09:43:44 Which is called the akra b ass I method. If you are interested you can look this up but not something you need to know. How are we doing on time? Okay. That is everything that we are going to say in this class about recurrences which is an essential technique when reasoning about the run time of recursive algorithms. Now that we have seen this general set up of recurrences and ways of solving them now we are going to transition in to the main material 09:44:47 Of the class which is how do we actually come up with algorithms for different problems and prove they are correct. The type of algorithm we will talk about is divide and conquer algorithms which we have seen examples of. I want to speak generally about this concept of divide and conquer algorithms. Divide and conquer is a general paradigm used over and over again in algorithms for many different types of problems. We will see a couple of examples in class. 09:45:43 There's many more in the text books. This is one of the most popular ways of coming up with algorithms is to use this divide and conquer approach. All divide and conquer algorithms have the same sort of over all structure. It consists of the following three main steps: The first step is to divide the problem you are trying to solve in to smaller subproblems. You can think of in the convex hull problem you can take the whole set of points 09:46:29 We are trying to find the convex hull for and split them in to two sets of points. Now we can consider the convex hull of each of those sets independently. Once we have done this division then we conquer those subproblems. We solve each subproblem using a recursive call to the same algorithm. This is really the essence of why divide and conquer is a nice paradigm because we don't have to worry about how we are solving these subproblems. 09:47:18 We get it for free because it's a recursive call to the same algorithm. The part we have to figure out is once you have the solutions for the subproblems how do you put those together to get a solution for the original problem? The final step is to combine the subproblem solutions in to an over all solution. This is the general structure of a divide and conquer algorithm. It should look familiar to you from the divide and conquer convex hull algorithm we saw. 09:48:08 Where we split the set of points in two and found the convex hulls of the left half of the points and right half of the points independently. Then we took those two convex hulls and by adding the tangents between them got a convex hull for the original set of points. In general, this approach is helpful when it's not clear how to solve a large problem but you can rewrite it in terms of smaller problems of the same type. You have some large problem 09:48:59 And you don't know how to directly write an algorithm for solving it, but if someone gave you the ability to solve smaller versions of that problem then you could bootstrap, build on the smaller solutions to get an over all solution. What this paradigm does for you is, as I was saying before, it makes it so you don't have to worry anymore about directly solving the problem. This conquer step you get for free because you are calling the same algorithm on a smaller version 09:49:59 Of the problem. It's often easier to come up with away to do this division and combination than to directly solve the problem. Another way of saying this is the conquer step is free. It's done automatically by the recursive calls. All you need to figure out is how are we going to divide the problems up and how can we combine their solutions in to an over all solution? If you can figure out those two things then you have a divide and conquer algorithm for the problem. 09:50:41 You can use these techniques for recurrence to see if it's efficient or not. Let's look at another example of a divide and conquer algorithm. One of the simplest divide and conquer algorithms but widely used in practice in an important algorithm is merge sort. Those of you who have been to section already this week have seen this. I will say more about it today. The idea in merge sort is we are going to sort a list. You have some list of integers. 09:51:32 Doesn't matter what they are. The idea is we will apply this paradigm to sort the list. What we will do is take the whole list and split it in two halves. We will sort each of those independently. Recursively here and glue those together to sort the whole list. The idea will be if we have some list we will cut it in half and apply the algorithm recursively to the left and rite halves so we have a assorted list here and another assorted list here. 09:52:56 Half of the elements are in one or the other. We need to figure out once we have these two assorted lists how can you combine those in to one over all sort list? Let's think about how we can do that. The idea is fairly straight forward. Let's say we have two lists. Let's call them B and C. They could look something like this. Maybe here's list B. It's got some elements in it. Let's say they are integers. Let's say it's three, five, five, seven. 09:53:48 It's already in sort order. We are assuming it's in increasing order. We have another list, C. Doesn't have to be the same length. Which is also in the assorted order. Maybe this list. How are we going to merge these two lists in to a single sort output list? Let's call our output list D. It will be empty to start with. The idea is simple. We will look at the first element of each list. Because these two are assorted. The first element of B has to be the smallest element in B 09:54:48 And the first element in C has to be will smallest element in C. The first element of D the output list has to be one of these two. We should pick which ever is smaller so we make sure our output is in increasing order. What do we do? We look at the first element of each list. Which ever one is smaller we remove it and add it to our output list. In this case, one is the smaller of these two. We will pop that off. We will add it to our output list, D. 09:55:19 Depending on how you implement this you may not have to delete this. You can have appointer keeping track of which element of C are you looking at next? Now you would advance this arrow. Now we are saying we will look at four next. I will not worry about the exact details of how you implement this but you can check out the text book for that. Now we have gotten rid of the first element one. We repeat this. We look at the first element of each list. 09:56:03 We compare three and four and take which ever one is smaller. In this case it's three and we add it onto the list. We cross that out and advance to this element. We can keep doing this. Now four and five which is smaller. Four is. We will add that. Cross that out. Go here. Now five is smaller. We will add this. Again, five is smaller. We add that again. Now, six is smaller. We add this. We have exhausted one of the two lists. 09:56:53 The last thing we do is we repeat this until one, at least one of the lists is empty. Then we can just append the rest of the remaining list on the end. In this case there's nothing left in C. Whatever is left in B we will tack it on at the end. That's the procedure. Basically we are just going to iterate through both of these arrays moving forward once we have taken an element off and at each step we look at which of the two elements is smaller. 09:57:28 We take the smallest one. Put it on the list and move forward in that particular list we took it from. You keep going through. Eventually every element will be removed and added to the output list. Because we are in sort order this insures you add things onto the output list in sort order. I have not formally proved this procedure always gives you a correctly assorted output list. I think we will not have time today. We will see. 09:58:09 If we have a few minutes at the end I will indicate how to do that other wise I will put a note in canvas. You can prove this with loop and variance which we will come back to later in the course. Let's assume this procedure works correctly. Let's think about how long this takes. The run time of this procedure, what will that be? We have to look at each step the first element of each of these two. Take which ever one it is and add it to the output list. That takes time. 09:58:56 Advancing in to lists by moving appoint or one element over takes constant time. Each repetition of the loop takes constant time. How many loops do we have? Look at each element of the list. Each element gets added to the output once. The run time of this procedure is going to be linear. If we write it in terms of the length of these lists it's something like theta of the length of B plus the length of C. This is linear in the sizes of B and C. 09:59:41 A question about proving the run time of merge sort. I have not proved what it is. If we have two assorted lists how do we combine them to a single list? What I said above is we can use that to build a recursive algorithm for sorting. Let me write that down and then we can think about what the run time of that is. Now that we have this sort procedure let's write down formally how merge sort will work. 10:00:23 Merge sort, I will write it as pseudo code. Let's say you are given array A with elements from zero up to N minus one. This is just a notation I will use to say it's an array with indexes of zero up to N minus one. In any recursive algorithm we have to have the base case to represent infinite recursion. What's the base case going to be in this case? If you give me a list that has only one element in it or if you give me an empty list that's already assorted. 10:01:02 There's just one element then it's already in order. Our base case is if N is less than or equal to one. If you give an array with a single element or empty list. Then we can just return A. It's already assorted. Other wise, we are going to do divide and conquer. We will split the list in to halfs and sort each half recursively. We have to figure out how we will split the list. The easy way is to take the first half and second half. We will find the index. 10:01:40 That's the mid point of the list. By saying let's just take N over two and to make sure that's an integer I'm taking the floor here. Now we will call merge sort recursively on each of the two halves. We will first sort the first half of the list. We will say call merge sort on just the first half of A. Not from zero all the way to N minus one. Let's only go to M minus one. We picked M to behalf way up the list. This is the first half of the list. 10:02:22 We will do the same thing for the second half of the list. Now from M because we went up to M minus one. Now we start from the next element which is M. To the all end of the list which is N minus one. That's the second half of the array, A. Now we have these two assorted lists much the assorted versions of the left and right half. Now we can apply the merge procedure we just saw to get an over all assorted list. We will call merge on B and C. 10:03:05 Question, what is B and C? I'm defining variables in my pseudo code. I'm saying call merge sort on this array. Call the result of that which is some array, B. Call the result of this recursive call, C. These are two other arrays B and C that we get as the return value from these recursive calls to merge sort. I'm saying we can pass those in to this merge procedure where merge is this process I talked about up here. Which I didn't write out formally in pseudo code. 10:03:50 You can write it out by making this informal description more precise. This is the procedure above. The claim is if we return D this is exactly what we want. We have recursively sortsed the first and second halves. If we assume that B and C are now properly assorted by the recursive calls then by the correctness of this merge procedure D will be a assorted list containing all the elements of A not just from the first half but the second half. 10:04:41 D will be a correctly assorted version of A which is what we want. Does everyone get the idea of how this algorithm works? The next thing to do now that we have come up with this algorithm is to prove it works. A question here. Does it completely sort B first and then C? Yes the way I wrote it here we are first making a call to merge sort to sort the first half. So it's sorting B. We don't get to this next line sorting the second half until this 10:05:19 Recursive call has returned. B has been computed then we compute C. We are not sorting B and C at the same time. If you have a parallel processer you can do B and C at the same time because they are independent from each other. We are looking at the first half and second half separately. We are doing the first half and then the second half. Informally we can see how this works. How do we prove this algorithm is correct? 10:05:54 I want to show you how you do that for a divide and conquer algorithm. Merge sort, the way you prove its correctness is very much the way you would do the same proof for any divide and conquer algorithm. So far we have talked about run times. How would we analyzed run time of a recursive algorithm. You can do that here. In section we are doing this. Looking at this code, the description of merge sort. From this extractsing a recurrence. 10:06:35 And solving that to get the run time. I will make a note here. The run time of merge sort, see the worksheet from section. I will not go through it here. We are asking you to do it in section. It's following the idea we have talked about previously. You look at this code and extract from this recurrence which defines the run time of the total algorithm in terms of these recursive calls. We have recursive calls here. You have to account for the amount of time spent in the 10:07:07 Nonrecursive parts. These lines here. We know how much time the merge takes. We have done that here. You can come up with a recurrence for a merge sort. Solve that. Find out how much time merge sort takes. I will not go through that here because it's in section. The other thing that's more important than computing the run time is proving that this algorithm works. How do we do that? When you have a divide and conquer algorithm like this, 10:07:41 The natural way to prove the correctness is using induction. The correctness of a divide and conquer algorithm depends on the correctness of the recursive calls. Induction let's you reason about that. To say let's assume the algorithm is correct for smaller problems. That means the recursive calls will work correctly. Can we use the correctness of the recursive calls to justify the correctness of the over all algorithm? That's the intuition for why we use induction. 10:08:58 Let's go through this in detail. First thing to do is set up what it is we are trying to prove more formally. What we are going to say is we will prove that for any list, A and let's say we have a length of N, merge sort of A is a assorted permutation of A. What does this mean? Assorted would mean it's in increasing order. If you want decreasing order we can change it to decreasing. The way I phrased it before it was increasing order. 10:09:41 It needs to be a permutation of A. Meaning the elements you return from merge sort need to be the same elements in the original list. We don't want to drop elements or add any new elements. It needs to be the same elements you just rearranged them so it's a permutation. What we will do is we will prove this by induction on N. We will say if we can assume it works for arrays of lengths smaller than N we will use it so prove it works for arrays of length N. 10:10:30 We will prove this by induction. In particular, strong induction on N. How is that going to work? I will put the pseudo code back here for a second and bring it back when we need it. To do a proof by induction like we saw last time there's two parts there's base case and induction case. The base case here, what's that going to be? We are doing induction on N which is the length of the list. What is the smallest possible length you could have? 10:11:14 Zero if you have an empty list. Question, can I explain what is strong induction? Strong induction is the form of induction where you prove that if the statement holds for all values strictly less than N then it holds for N as well. If you can prove it holds for N equals zero and whatever it holds for everything less than N then it holds for N strong induction says it holds for all N. I will write that down for you. Note here, strong induction says -- 10:12:16 I will make the base case zero to make is simple. If some property, P, holds let's say P of N. Holds for N equals zero and if it's the case that for all M less than N the property holding for M, if that implies that it holds for N then for all M property P holds on N. The idea is if you can prove something holds at zero and that for any N if it holds for all M less than N then that implies it holds for N. Then it has to hold for all possible numbers. 10:12:57 Because it holds at zero then does it hold at one? What are the values less than one? Just zero and you proved it for zero so that implies it holds for one. Would it hold for two? It holds for zero and one which are values less than two so by this it holds for two, et cetera. By the principle of strong induction then this property P holds for all N. I should put for all N here. That's strong induction. If you are not familiar with this we have the hand outs about this posted on 10:13:43 Canvas and piazza. The base case here, natural base case is N equals zero because you have an empty list. I will allow N equals one because if we look back at our pseudo code from merge sort the base case of merge sort is N less than or equal to one. That's the natural base case to use in our proof. Our base case is N less than or equal to one. In that case, what are we trying to prove again? We are trying to prove that merge sort of A 10:14:43 Is a assorted permutation of A. If (INDISCERNIBLE) is less than or equal to one then this array A contains either zero or one element in way case A itself is already assorted. What is merge sort of A? By our definition when N is less than or equal to one we return A. In this case, merge sort of A equals A by definition of the algorithm here, but A is already assorted. Because it has at most one element. We have proved the induction hypothesis that 10:15:41 Merge sort of A is a assorted permutation of A because merge sort of A is definitely A. And it's assorted. The base case is established. Questions about this? We have seen when the input has size one or less merge sort is correct. Now to finish up this proof we need to do the induction case. For that, now we need to consider what happens if we are not in the base case. We say take any N which is strictly greater than one. Not in the base case. 10:16:42 Since we are doing a proof by strong induction we can now assume the induction hypothesis holds for all values of -- all input sizes less than N. Take any N greater than one and assume the induction hypothesis which is this statement here, holds for all K strictly less than N. If you have -- if the length of the list was anything smaller than N then the induction hypothesis holds. Maybe I should -- if it's unclear about N versus K I want to distinguish between 10:17:17 The value we are trying to prove it for which is N and now any value which is less than N. If you have any length of the list which is less than N then we know we are allowed to assume the induction hypothesis holds. A question here why is it strictly less? Other wise we would have circular reasoning here. We are going to try to prove the induction hypothesis holds at N. So we can't assume it holds at N. We can assume it holds everything up to but not including N. 10:18:05 We are assuming induction hypothesis holds for all lengths up to N. Now what does this imply for our pseudo code? If we look back here we are not in the base case. We will not return to this point. What's the next thing the algorithm does? It computes N which is M over two. Then M as computed by the algorithm that's the floor of N over two. That's going to be strictly less than N. Because N is at least two. This, when divided it by two and taking the floor is 10:19:24 Strictly less than N. By the assumption B which is the merge sort of A starting from zero up to M minus one is a assorted permutation of that part of the array we gave to it. This array we are passing in to merge sort has length M because it's going up from zero to M minus one. M is strictly less than M. This merge sort works critically on this list. This is a assorted permutation of the first half of A. Similarly, if we look at what happens in the next line now we are computing 10:20:29 Merge sort on the second half. The induction hypothesis is also going to apply to that. Why? What's the length of that list? We also have the length of the second half of the list M through N minus one. The is (Writing on board). That again is strictly less than N. By assumption the induction hypothesis, this array C which is the merge sort of the second half so that's from M up to N minus with one is a assorted permutation of its input. 10:21:16 We are calling merge sort on the second half of the list here. This second half of the list has length N minus one minus M plus one because it's the indexes between N and N minus one. That's the other half of the elements. We took the floor of them and put them in the first half. The remaining part is the ceiling of N over two. That's the number of elements that go in to the second call C. That's strictly less than N. 10:22:03 Our induction hypothesis is anything strictly less than N the induction hypothesis holds. The assumption we can make is the induction hypothesis holds. This recursive call works correctly and returns a assorted permutation of input which is the second half of the list. Question of why is it M plus one and not M minus one? The reason here is for example M was one and (INDISCERNIBLE) it's N minus one minus M plus one. 10:22:45 Just to count that correctly. If this is two, element one up to two then you want to do two minus one is one plus one. You need to count both end points. Why couldn't we pick N equals two in our induction case? You could have N equals two. We are saying you could take any N which is strictly greater than one. N equals two would work fine. You will notice if N equals two M is still strictly less than N. We have two over two which is one. 10:23:48 The floor of that is one. M would be one. N over two the ceiling is also less than. Okay. Still confused by M plus one. The reason is what is the length of an array from M up to N minus one? If you (INAUDIBLE) let's call it two up to five. What's the length of this list? This has length five minus two plus one. Because you have element two, three, four, and five. We need the plus one to get the length correctly. The length of an array where the first index is this and the last is that 10:24:28 It's (INDISCERNIBLE). N can't be one. It has to be strictly greater than one. That's why we say here the base case handled if N was one. Now we say if N is strictly greater than one. That's what insures the floor here and ceiling there are strictly less than N. You are right if N equaled one then the ceiling of one over two would be one. It wouldn't be strictly less than. It's important we are taking N strictly greater than one. Let's finish this proof off. 10:25:38 Now we know B and C are assorted permutations of the first and second half of the list here. Since B and C are assorted by the correctness of the merge process which I have not proved but I'm saying for now assume that. By the correctness of the merge procedure the output of it, D, is a assorted permutation of B and C. It has all the elements in B and C in assorted order. Con tonated with B and C. B and C as we said are permutations of the first half 10:26:31 Of the array and the second half of the array. That means D is actually a assorted permutation of the original array A. Since B is a permutation of the first half of A and C is a permutation of the second half of the array M up through N minus one D is a permutation of all of A because we have all the elements. Everything up through N minus one and everything from M onward. That establishes the induction hypothesis for N. 10:27:08 Because what was the hypothesis? That the merge sort applied to the array is the assorted permutation of the input. We have shown D, the output array is a permutation of A which is the original input. By strong induction this hypothesis here holds for any list A of any length N. We have proved the correctness of merge sort. All right. We are out of time. We will stop here. I will hang around if you have questions other wise see you on Wednesday. 10:27:11 Have a nice weekend.