C++: Preparing The Coding Interview | Programming Made Easy | Skillshare

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

C++: Preparing The Coding Interview

teacher avatar Programming Made Easy, Software Developer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Welcome to this course!

      2:00

    • 2.

      Big O Notation

      4:39

    • 3.

      Array and vector overview

      6:38

    • 4.

      Deleting in an array

      5:06

    • 5.

      Linear search in an array

      4:19

    • 6.

      Binary search in an array

      6:30

    • 7.

      Strings

      3:14

    • 8.

      Concatenation and finding the length of a stringConcatenation and finding the length of a string

      2:30

    • 9.

      Changing case of string

      3:43

    • 10.

      Counting words/vowels

      6:44

    • 11.

      Reversing of a string

      4:10

    • 12.

      Checking palindrome

      4:41

    • 13.

      Check if 2 strings are anagrams

      5:22

    • 14.

      STL sort() function

      5:36

    • 15.

      Bubblesort

      8:17

    • 16.

      Quicksort

      10:25

    • 17.

      Trees

      8:54

    • 18.

      Traversals: DFS, BFS

      9:32

    • 19.

      Check for children sum property

      5:19

    • 20.

      Sum of all the nodes

      3:39

    • 21.

      Check if all the leaves nodes are at the same level

      5:05

    • 22.

      The balanced brackets problem

      8:44

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

84

Students

--

Project

About This Class

Algorithms? Covered. Data Structures? They're here. Lots of questions with well-explained solutions? Yes.

If you're nervous about your first coding interview, or anxious about applying to your next job, this is the course for you. I got tired of interviewers asking tricky questions that can only be answered if you've seen the problem before, so I made this course! This video course will teach you the most common interview questions that you'll see in a coding interview, giving you the tools you need to ace your next whiteboard interview.

Coding interviews are notoriously intimidating, but there is one method to become a better interviewer - and that is practice! Practicing dozens of interview questions is what makes the difference between a job offer and another rejection email. This course is going to not only give you dozens of questions to practice on, but it will also make sure you understand the tricks behind solving each question, so you’ll be able to perform in a real interview.

Many developers who are "self taught", feel that one of the main disadvantages they face compared to college educated graduates in computer science is the fact that they don't have knowledge about algorithms, data structures and the notorious Big-O Notation. Get on the same level as someone with computer science degree by learning the fundamental building blocks of computer science which will give you a big boost during interviews.

In this course, you'll get:

  • Clear explanations for every single problem to make sure you understand the solution and the code

  • An overview of the most important data structures to know about. These are presented for people without a CS degree.

  • A huge collection of common algorithm questions, including everything from 'reversing a string' to Tree searches

Meet Your Teacher

Teacher Profile Image

Programming Made Easy

Software Developer

Teacher
Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Welcome to this course! : Hello guys and welcome to C plus blast programming. The coding interview. My name is Alex and time of an experienced software developer that has been working with C plus plus for about four years. Now, the structure of this class is going to be split in key elements that are discussed aim document called interviews for software developers. First of all, we are going to talk about the complexities of an algorithm, both time and space. Then we will jump into arrays. Then we will look at strings. Then again, interview questions based on strings is the topic that we are going to concentrate on. Then also, we will look at a few very important sorting algorithms like bubble sort, quicksort and so on. We will also look at trees. They're traversals, and a few other interview questions that you can receive on DOM. And also, we will take a look at stacks and queues. The class is created for any party that either once to learn algorithms in the programming language of C plus plus, or someone that wants to get employed in the field of software engineering. And once you learn questions that can be given on interviews so they can base their interviews. There are no actual prerequisites for this course. Then your willingness to learn and an Internet connection. As far as the class project goes, it'll be a question that can be received in an interview scenario that you can look at. Think about the head, may be time yourself for 30 minutes and try to come up with the best extract that you get. So it called that sounds interesting. I look forward to see you in the next lesson. Let's get started. 2. Big O Notation: Welcome to Section two, big O notation. In lecture one, we are going to talk about big O, big Omega in time complexity. Let's get started. The big O notation is a mathematical notation that describes the limiting behavior of a function when the argument tends towards a particular value or infinity. In computer science, big O notation is used to classify algorithms according to how they run time or space requirements grow. As the input size grows. Not understanding it thoroughly can really hurt you in developing an algorithm. Not only might you be charged harshly for not really understanding Big O, but you will also struggle to judge when your algorithm is getting faster or slower. When analyzing algorithms for efficiency, we use big O. For example, the time, the number of steps it takes to complete a problem of size n might be found to be n times n to the power of two plus eight times n plus one. As n grows large, the n to the power of two term will come to dominate that. All other terms can be neglected. For instance, when n is 500, the term five times n to the power of two is one hundred, ten hundred times as large as the two times n. Ignoring the letter would have negligible effect on the expression's value for most purposes. Further, the coefficient became irrelevant if we compare it to any other order of expression. So the big O notation captures what remains. We write o of n to the power of two. Now, let's look at some examples of the time complexities that certain computer science algorithms. One is called constant. For example, an algorithm that determines if a number is even or odd would have this time complexity. O of log n is called logarithmic. For example, searching an element with binary search in a sorted array. I will present these types of search and how it works in a later section of n is called linear. This is the time complexity of iterating through an array for a variety of purposes. For example, to find an element and so on. O of n to the power of two is called quadratic. This is the case when you have two nested force in an array. This can be useful when you want to sort an array. Finally, o n factorial is called factorial. And we run into this time complexity when trying to, brute force solutions are calculating unrestricted permutations. In general, encoding interviews, you enter time complexity to, though as you can, for your algorithm to take less time to execute and be more efficient and optimize. However, you can start from a solution that is not that great if that is the first idea that you get to solve it and then work your way to a more optimized approach. Academics use Peek, oh, big theta and big omega to describe runtimes. In academia, big Omega is the equivalent concept, but for lower bond, printing, the values in an array is big omega of one. After all, you know that it won't be faster than this runtime. Big Theta gives a tight bound on runtime. We can say that the bonding of function from above and below is represented by theta notation. The exact asymptotic behavior is done by d Theta notation. In this course, we will use just the Big-O notation for our algorithms in the way that industry tends to use it by always trying to offer the tightest description of the runtime. 3. Array and vector overview: Hello there and welcome to section three arrays. In this section we will talk about a basic data structure named erase that comes up a lot in interview questions on coding. And it's very important for you to have a good grasp of it in programming. When we think of an array, we think of a data structure that resembles a collection of items, stored memory locations. The idea is to store multiple items of the same type together. This makes it easier to calculate the position of each element by simply adding an offset to a base value. Example, the memory location of the first element of the array, generally denoted by the name of the array. The base value is index 0, and the difference between the two indexes is the offset. For simplicity, we can think of an array fleet upstairs where on each step is placed the value, let's say one of your friends. Here, you can identify the location of any of your friends by simply knowing the account of the step they are on. Remember, location of the next index depends on the data type that we use. And it says, by default, regular arrays of local scope. For example, those declared within a function aren't left uninitialized. This means that none of its elements are sent to any particular value. Their contents are undetermined at the point theory is declared. But the elements in an array can be explicitly initialized to specific values when it is declared by enclosing those initial values embraces. For example, you can see here the first line in our image. The number of values between praises shall not be greater than the number of elements in the array. For example, in our image on the first line, was declared having five elements specified by the number in close the square brackets. And the praise is contained exactly five values. One for each element. Declare it with less. The remaining elements are set to their default values, which for fundamental types means they are filled with zeros. The value of the elements in an array can be accessed just like the failure of a regular variable. The same type. The syntax is name and then in-between brackets, the index. Notice that the third elemental Fu specified F-O-O. Then in brackets the number two. Since the first one is F0 of 0, the second one is F0 F1. And therefore, the third one is f o of two. By the same reason, its last element, It's F0, F4. Therefore, if we would write something like F0 05, we would be accessing the sixth element of F-O-O, and therefore actually exceeding the size of the array. In C plus, plus. It is syntactically correct to exceed the value range of indices for an array. This can create problems since X is in outer fringe elements do not cause errors on compensation, but can cause errors on runtime. This point, it is important to be able to clearly distinguish between the two uses that brackets have related to erase. They perform two different tasks. One is to specify the size of arrays when they are declared. The second one is to specify indices for concrete array elements when they are accessed. Do not confuse these two possible uses of brackets with arrays. At some point we may need to pass an array to a function as a parameter, C plus plus. It is not possible to pass the entire block memory represented by an array to a function directly as an argument. But what can you do is that you can pass instead its entries. In practice, this has almost the same effect and it is much faster and more efficient operation from this base point of view. To accept an array parameter for a function. The parameters can be declared as type, but with empty brackets are meeting the actual size of the array. For example, for a procedure. And then in the parameter list, int arg. Then some empty brackets. This function accepts a parameter of type array of int called ARG. In order to paste this function, an array declared as int, my array elements, it would be enough to write a code like this procedure of my array. So this would be an overview of the array type in C plus plus. Of course you can do many more operations with each of the elements. You can swap them and so on. Next, in the coming lectures, we are going to take a look at a variety of algorithms that very oftenly come up in coding interview questions. And we will look at their complexity, different approaches, and basically how to solve them so we can better be prepared for your future interviews. 4. Deleting in an array: Hello guys and welcome to lecture three, deleting in an array. In this lecture, we're going to talk about how to delete an item from an array. This question has two variations. From an array where we know what the value of the number that we want to delete from the array. And the variation where we know what is the position of the item in the array that we want to delete. Right here we have the variation where the value of the item is entered and not deposition, but the other one is very similar to this one. Let's run the code and after debt and some explanations of it. We can think about the complexity of this program as we would do in an interview situation. Let's start from the mean. As a good practice, It's always good to separate your functions from the main function and then call your function that you wrote for a specific question from the main function. In an interview question and an interview scenario, they might even give you the function without the body. So it's just a header. And then you write the function that should do how that started the SQL for. In our situation, as we entered the main function, we declared our int array that we are going to remove from, initialized it with some hard-coded integral values. Then we got each side dividing the size of theory by the size of an integral. Then we wrote x is six. We wanted to remove six from this array. Now, we will call the delete element function, which returns the new size of the array after removal, and also obviously removes the item from the array. This delete element function, as you can see, it has three arguments. The first argument is our array that we want to remove the item from. The next item. The item means the size of the array. And the last item is the number we want to delete from the array, in our case six. And as you can see, this is the arguments that we pass when we call the function. What this function does is it declares an i variable used to iterate through the array. And then in a for-loop, we iterate through the whole array, taking each element. And if the element is equal to x D element that we want to remove from our array. Then we break. X is found in the array and I is the index where x was found. We are going to decrease the size of the array because it is going to be one size smaller than it was before, because obviously we are going to delete an element from it. And then we're going to just move all the elements one space ahead. Lesley, going to return the size of the array. Here is the new length of the array. Then we are going to see out Monte Carlo and then iterate through it and show it. So if we run this, we are going to see the tower new array should be 1158910. You can see that's the array. So now let's think about diamond space complexity. The space complexity is obviously linear because we don't declare any other variables. If we do, they are considered constant. This space is linear and then the time complexity, well, we iterate through the array once here. And obviously once here. The time complexity is linear as well. Can we do this in a better complexity than this one? Well, no, because our element can be the first one, then it would still be linear because we need to iterate through the whole array. At this step. This was about deleting an item from the array. And you guys can do the variation where you delete an item from an array where you know the position is very similar to this one. But you can try that at home. And let me know how it went. 5. Linear search in an array: Hello guys and welcome back to lecture four. In this lecture we're going to talk about search in an array of integers, more precisely linear search. The scenario is that we have an array of integers that has numbers that are not sorted. So any kind of numbers that are integers. And the problem with S gas to find one number from this array and return its index. Now, we would obviously write a separate function from the main function that we call, would call from the main function and use that to find our element. As you can see in my code right here, we declare than a rate, it's hard-coded, values 2341040. Then the x value that's there. Then we are going to, as usual, use the size of helper function to calculate the size of our array. Then we are going to give our int, which salt the value of the search function. This function returns an int and it takes three parameters. Our array, the size of our array, and the number we wanted to find. Then going to iterate through it with the help of this auxiliary variable called. While we loop through it, we find our needed element, then we are going to return its index. At the end, we're going to return minus one, which means we didn't find it. Return i, as you already probably know, but I will remind you this. Tell you if you do not know, the return statement when you sit in your function, stops that function and it basically goes to where the function is called and returns that value. So what's after a return that's been heated? Function will not execute. This return minus one statement will only be heat if this return is never executed. So if our value was never found in the array, the result with the index of the value from the array that we want to find. If result is minus one, of course, going to say that the element is not present. And if it is going to say that it's present at the index result that's returned from our function. Right now, as you can see, if you run this program, we're going to see that element is present in index three. You know, the counting in an array is zero-based, meaning that the first index is 0. That's why this one will be one to n. The number of research for Dan is index three. Now let's speak about complexity. The space complexity is the size of our early, which is linear in regards to the input. Then the time complexity, well, the time complexity is given by our function because right here we iterate through our array once. That means linear time complexity. Now, can we do this better than linear? Well, no, because at worst case, the element that we want to find this position and that means we have to iterate through the whole array to finally find it in the last position. And that would take linear time. In this problem, both space and time complexity is hardly linear. Let's move on to the next lecture, where I will show you a more efficient way to do this. But under a condition, and that is the array being sorted increasingly or decreasing. 6. Binary search in an array: Hello guys and welcome to lecture five, binary search in an array. This is basically the first more serious algorithm that we are going to approach in this course. And this one is more often given in interviews. And maybe not these basic variation, but other variations that can have other constraints or not asked you the ceaselessly to implement this. But another type of problem where you need to use this type of algorithm. The problem is that given a sorted array of n elements, you should write the function to start to give an element x in this array. A simple approach, as we have seen in the last lecture, would be to do linear search on your array. The time complexity would be linear, as we saw in this space complexity would be linear. But another approach to perform the same task using binary search and given the fact that our array is sorted already. So what binary search basically does, instead, it searches a sorted array by repeatedly dividing the search interval. Inhale, begin with an interval covering the whole array. If the value of the search key is less than the item in the middle of the interval. Narrower the interval to the lower, help, narrow it to the upper hand. Repeatedly check until the value is found or the interval exactly. The idea of binary search is to use the information that the array is sorted. Reduced the time complexity, logarithmic one. Now, if we look at this picture, we can see an example. We have this array that has 2581216233856172091. We are going to take m in the middle would be low and it would be 0 and h would be nine. The three indices we are working with, we need to search for 23. Well, we are going to check, and 16 is smaller than 23. So we are going to move to the right. We are going to take l, m, the arithmetic average of n and h. And we can see that 23 is smaller, 36. Going to search in the left half. And right now would be six, because it will be m minus one. M would be five. Right here we searched for 23 without even looking at items like 5812 or even 72. Now let's look at the code and see how it works. The main function is very resembling of the last main function that we use on linear search on an array of integers. The only difference is that function that it uses and returns the indices where our number was found. This binary search function, as you can see, takes four arguments. The first one is our array of integers. The second one, the third one is the R. Or in the case that this picture would be h. Because right here is right, there was high. They mean basically the same thing. And then x is the number that we went to search. We are going to make recursive calls. Going to start by saying, aren't so right is bigger or equal to L. We're going to declare meet in the GRE and give it basically the average of R and L. If you are asking yourselves, why isn't this L plus R divided by two? And it's written like this. Well, this firstly does bear minus l and then add. This helps avoid cases of overflow. Number is big enough to exceed the memory and for your program will basically to crash. If array of meat was equal to x, the number we weren't searching for, then we should return the index because we found it. If it's bigger than the element we are searching for, then we can only look in the left sub-array. So we are going to recursively call binary search of ARR Again L. And then instead of area I'm going to call mid minus one, we are going only to look in the left sub-array. In the other case, we're going to look in the right subarray by giving the recursive call instead of l In the second argument, mid plus one. Lastly, if no other return was hit when returning from the recursive calls. Now going to return minus one. As you can see, if we run this program, number ten was found again at index three. As I have said before, the space complexity is linear because we declared the array, then the time complexity is logarithmic. Thanks to this nice algorithm. If the array is not sorted though, you cannot find an element in a better time complexity than linear. This is only made possible here because we know the array is sorted and we have this way, quicker way to look through it. This is about binary search. You can try to implement it on your own without looking at this algorithm. This is an important interview question and an important algorithm that you should really know very well. 7. Strings: Hello guys and welcome back to section four. In this section, we are talking about strings. Strings are objects in C plus, plus the three present sequences of characters. The standard String class provides support for such objects with an interface similar to that of a standard container of bytes. But I think features specifically designed to operate with strings of single-byte characters. Here we can talk about member functions like swap, that swaps the content of two strings, append, that appends a string to a given string and returns a pointer to the resulting string. Inserting, erase, find some SDR and many others. I will attach a picture here with descriptions for each of them so you can read them and understand what each of them does. We can also talk about overloaded operators, such as a bending of two streets. They stand with the plus equals sign concatenation, this time with the plus sign. The equality operator, implementing through to equality signs and so on. This glass also has a variety of constructors. The empty one that creates an empty string. The one that takes as the argument, the string in-between brackets. You can write your string and it will initialize that drink object with the stream that you right there. The one that takes an integer and a character and instantiates the string with that character that will be repeated by the given number of times. To use strings, you must include an additional header file, illustrators code that will be include. And then string dot h in-between triangle parentheses. Also, you saw that you might include iostream that comes from input, output stream, and you usually need to write and read keyboard input. Note that this class handles bytes independently of the encoding, is used to handle sequences multiplied or variable length characters, such as UTF eight. Members of this class, such as length or size, as well as its iterators, will still operate in terms of bytes, not actual encoded characters. In the next lectures, we're going to take a closer look at some interview coding questions that might come up that use strings. Let's get to work. 8. Concatenation and finding the length of a stringConcatenation and finding the length of a string: Hello guys. In this lecture we are going to talk about contact nation and finding the length of the street. Let's start by talking about concatenation. The plus operator can be used between two strings. Do I add them together and make a new string? This is called concatenation. Let's treat it in C plus. Plus is actually an object, as we've already talked about. In the last lecture. Nice object contains functions that can perform certain operations on strings. For example, you can also concatenate strings with the append function. You can do these in whatever way you prefer to. Talking on a more concrete level. You can see in your code something like string S equals to a plus b, where a is another string and B is also a string. And concatenate them by making this twin of a and B at the end. And it will basically make one is three, contains both of them first day and then B. Now to get the length of a string, you can use the length function has deep. You might see some C plus plus programs that use the size function to get the length of the string. This is just an alias that blank. It is completely up to you if you want to use length or size. Now of course, if you wanted to implement this problem without using these pre-built function, it will be pretty simple. You will have to iterate through each character of the array with a for loop and then have an integral instantiated with 0 incremented for each character. That way you can get the length without these pre-built functions. You can access the characters in a string, as you would in an array of cars by referring to its index number inside square brackets. To change the value of a specific character. String, refer to the index number and use single quotes, because that's a character. 9. Changing case of string: Hello there. In this lecture we are going to talk about how can we change the case stream. The problems here is that we need to convert all the uppercase letters to lowercase and vice versa. Industry. New approach here would be to iterate the string and use the ISA per pre-build function to determine if each character is in actual application or not. If it's uppercase, we will convert it to lowercase using the CO2 lower pre-built function. And if it's not uppercase, converts it to uppercase using two upper pre-built function. Now, we can also do this without these pre-built functions by adding or subtracting the value 32. Because that's the difference in numbers between an uppercase and lowercase value. For example, the letter uppercase has an ascii value of 65, and lowercase has an ascii value of 97, which is 65 plus 32. You can also use this little heck to do this problem. If the interviewer specifies that you are not allowed to use any pre-built string functions. Now, if we look at the code, we have this main function where we declare an STR stream, also specifies the std scope because we didn't use using namespace std. So you can either write the using namespace std or say std. And these two double dots before Amy, STD member that you write. In the next line, we initialized STR string with this string right here. And then we call the transform function on this STR with using three iterators from beginning of the SDR string to the end of the history or string, then we aren't going to breathe in March called The Change Case for each character of it. This is just a way to iterate through it. At line 16, The Change Case functions takes a character and it returns a character, as you can see in its header. And it's just an if function that verifies if the character is uppercase, then it returns the lowercase. And if it's not means that it's lower case. That case we are going to return the upper case character cell after we transform the whole string with this function, it will pretty much every first Casey. Then we are going to write it on the output command prompt. And as you can see, if we run this code, we get the exact string that we initialized reversed case. I've already said you can use the 32 little hack to do this problem without any built-in functions. 10. Counting words/vowels: Hi guys and welcome back to lecture four. In this lecture we are going to talk about how you can come towards the vowels in a string. Basically a bigger string that has spaces in between words. Something like samples or Pablo's can be if an award. What the problem sounds like is that the function that you are supposed to write receives an argument that's a string, and then you need to return the number of vowels. For dinner of words. This is the problem we're going to talk about today in this lecture. As you can see, I already coded it up for you, but we are going to run, as we usually do. Commend, going to discuss what everything basically does is usually we start from the main function. Here we declare a string that I called SDR and Nike feet ABC space. And now we have two functions to count the number of values it has. First function receives the third character, returns brilliant. What it does. Thanks this character. Uppers. For example, it would be a lowercase. It return it to uppercase. We can verify against the upper teeth spotless and not the lowercase too, because then we would have had five conditions here with the OR operator between them. What we do is return there, the character. Character. Character is a character like this, E, I, O, U. Any of these seats true? Then we return to this function. As you can see, it's called from another function is called count vowels. This one receives a string parameter based TR. Initializes and integrate, count. The value 0. Then we iterate through the string, through each of its characters. Then if the dead character vowel, then we up the account. At the end, we return it. This is a very simple method to return the number of vowels string. Now let's talk about the complexity of this algorithm. Well, first of all, this space is linear because we don't declare more than this treatment itself. Then the time complexity is linear to, because we iterate through each of the characters from the string, both time and space and place. These are linear big O of n. Now, moving on to the next problem, going to count the words. That's going to do this by writing a function that receives from parameter that's a stream and then returns an integer. Clara Decker, now that we initialize with 0 and a character that we call preform previous death initializes with space. Now we eat the way through the stream that we receive as the parameter. If the current character space in the previous lesson, we increment. Now, what does this mean? Well, it means that we found the beginning of a new word because the character, now it's not the space in the previous space, used to be a new word, one. Lastly, we're going to update previous with x of i. When we look in the next iteration. Current, previous, hence the actual previous bear. Decent orientation. We are going to return the number now. Thanks, you can't see. If we call this function, it returns two. Because our string ABC space D0 would be considered to have any abc. And then these are not actual words. But if you're typing a sentence that we didn't make sense, it would be worth. Now talking about the complexity of this algorithm, I think it's pretty clear that this space is in regards to the input, because we don't declare anything more than the stream itself. We have linear space complexity, time complexity. It would be linear as well because we eat the retarded once through the stream to check the condition and the previous value. Right here. We discussed two basic algorithms that come up. A few questions. Starting problems. They are very basic, but it's very important to start with the very basic ones in understanding the complexities and how to do them optimally. Because you can then build upon the foundation, depth. You have to solve and understand more complex algorithms and problems in the future. The next chapter we're going to talk about have to reverse a string, which is a more commonly met interview question. 11. Reversing of a string: Hello guys, welcome back. This lecture, we're going to talk about how to reverse a given streak. How are you going to do this? Problem says, is that given this gene from input, from keyboard or a file, you just give it the value I hard-code the task matric Jeff tapestry, and the problem is to reverse it. So for example, if we have a string, if your function with ideally we tend to stream refers to the debt would be reversed order. Not going to discuss how we implement this function and what its complexity each cell, first of all, we declared a string. It says Welcome to the squares. Then we just call this function on. This function doesn't return anything. It's a void return type function. We initialize the length of the stream, then we iterate to the health of the stream. What we do is we swap in-between them, the matching characters. For example, when I see or we are going to swap these T-R-I-E tasty r i n minus u, o minus one, minus one. Because zero-based counting decent arrays, we're going to talk to swap the first element, which is 0, element which is minus one, a zero-based. For example, the string. We're going to take intent G minus one. It's going to take the one indexing then n minus two, which is then swap them and then swap them. Points. We heat the middle of the street, we stop. This is basically the most optimal way to do this operation. And this, you can see if I heat, we are going to receive these gene in reverse. Now, let's talk about space complexity of this algorithm. First of all, this space complexity is linear regards because we don't receive the time complexity. N divided by two, because half of the array stop matching characters in-between them. As we know, only the n and its power. The Big O notation of time complexity would be, as well as the space complexity be linear to this algorithm. The next lecture, we are going to see how manage to check if a word or a string is a palindrome. Benadryl, meaning that this dream that you have first is the same. Let's move on and talk about how can we do that. The complexity of that algorithm would be. 12. Checking palindrome: Hello guys and welcome back to the course lecture. We are going to see how can we check if it worked? Meaning a string is a palindrome means that it's the same. It's the same if we read it from left to right. For example, a BBA would be a Benadryl because probably it would be ABB form. That would be still a BBA. This one would be a bit of drama as well, but these ones wouldn't be because we read it from left to right beyond the half-life, the beginning. Repeat from right to left. We have two LC WE. Now that we have understood what the problem is, you would do an interview. The first step is to understand what the problem once from you. We can think about how to solve it. But since we just talked about how to reverse a string, this is a very similar problem in these very easily done if we have the reverse algorithm, because we would just need to check if our stream would be equal to the reverse of it. With p equal, it would be probably true. But now we are going to take another approach to this problem. Solve going to function as a parameter string. And then we are going to not return any degree because you are going to just imprint on the output this gene that receive as a parameter. The parameter is going to start off by initial values 0 and then age with the size of our stream. Then, while index, index, index, this case XDR of not equal to the STR. So the magic character from the beginning, not the scene we are going to print. The string is not apparent. Draw me the return to function h and del cross paths. Meaning that age is not inverted, means that the whole stream, we can draw this. You can see if I drag, it checks out for each of these tricks. So a BPA, a BB, CC, BB or not. Complexity. Complexity easily regards today in, but because we've got this napa constant other than the input stream, would be the case, is two divided by two because we all need to have this gene. We reached half of h would be the while loop with IT. Complexity is linear instagram regards to the precise, these would be obviously topo stopped him away to do it. Because you still have to check trough of theory to make sure all the characters are equal so that you can confirm that your students about in the last lecture of this section, the next lecture. We are going to check if two strings are anagrams, meaning post the same characters. There's more. See how can we do to be the most optimal algorithm. 13. Check if 2 strings are anagrams: Welcome back. In this last lecture here talking about how can you check given strength? Words? They can be sentences. Meaning they are composed of characters. What do I mean by sample? We have two words, such as dog. Dog would be anagrams because one T1, 01. This would be an agreement anymore because the count within these run with f one g, and this one we have two G's anagrams. The problem asks us to write the function to check if two strings are or are not anagrams. So as you can see, the main function we start by initializing each of these strings. We are calling a function that takes as parameters two streams will be true. If this G is I integrate cosine function, we declare two integers that links. We are first going to check the strings have the same length. It means they can't have the same characters. Because obviously two amounts of characters can't be equal before the speaker TPI out, they're going to sort strings. The stars, sort them based on ascii values, sort them in alphabetical order. Then we are going to be three genes at the same time. Did here we use then one, but we could have used because basically the same. We wouldn't be in this function, this line because it could hype already returned false boolean. We iterate through each of these genes and we check their character, say equal, not equal, we return false. We reach the end of them instead, talk characters are equal and we can return true. We put this function that returns each state one to ten. We can these streams, grams will be charted. It otherwise we can say that they are not. For example, if we see these two strings, the right sample, you can see that they are n. If we change the second stream, what it would do is basically with this condition, be a false or we can even make them the same size, different letters and the two, it's still black patients you can see right here because they would sort them in alphabetical order and see that one is p, one is G. Best this if statement trend here, three times false. Now let's talk about the complexity of the program. Saline regards space complexity. We can consider the first streaming. Space complexity would be big O of n plus m. Thank you guys for staying with me. In this section. We are going to continue with the next section. Very important topic regarding the interview coding questions. Sorting. Either if we talk about the nursery or as you can see, it can be very useful when we work with strings. So we're going to cover up their complexities section now. 14. STL sort() function: Hello guys and welcome back to lecture two. In the second lecture, we are talking about the sort function that's available in the standard library of C plus plus. You can use as an easy alternative when the interviewer isn't actually trying to test your ability to sort an array or some data structure, but it is required in order to do the rest of your problem. You can try to use these sort a function. And it's a scenario where you need your items sorted, but you don't need to actually implement the whole algorithm by yourself. Sorting is one of the most basic function supplied data. It means obviously arranging the data in a particular fashion, which can be increasing or decreasing or whatever else comparison function you might use depending on the data structure that you have. In more complex environments. Suppose you have structures of type cat. You want to order them by the number of whiskers they have. You will need to implement this specifically comparison function. You can actually pass third argument to this function. We will see that later. It will sort them basically by number whiskers. There is a built-in function. As I've already said, the C plus plus STL comes from standard library. Name of this function. Internal uses interests are in more details about each implementation because the interviewer might even SQ, how these function implemented if he sees that you use it. Well, it using a hybrid of quick sort, heap sort, and insertion sort. Depending on a few factors. By default it uses quicksort. What if quick sort is doing unfair partitioning more than n log n time? It switches to heap sort. The array size becomes really small. It switches again to insertion sort. Now, if we take a look at this code right here, we can see this function right here in action. You can see in the main function we looked at unary that we initialized hard-coded array. Then we got size using the size of operators. Then we use this function right here that takes two iterators. So we gave it ARR, which is the pointer of the first element of the array. Then ARR plus n, which is the end of the array. Then it sorts it. To see it in action. We also printed it on the screen after sorting and as you can see right here, sorted it increasingly. Now as I've said, your kin past this sort function, third parameter of comparison that would order the elements in a different fashion. Show you this. I will keep this sort function, parameter, comparison function that sorts the elements decreasingly. That's called greater beat. It altered our decreasingly. We can of course, implement your own function right here that you can write yourself above the main function that takes two parameters and returns a boolean on whether whatever condition you want to reorder is true. This year would be very interesting and easy way to bypass sorting in an interview. As I've said, if the interviewer is that debt, curious to see if you can actually sort the array yourself or S2 for a specific sorting algorithm. Also, given time complexity by its implementation, it's n times log of n. And that's actually the best complexity by which you can order an array. Now, in the next few lectures, we are going to take a closer look at some sorting algorithms that are actually implemented. The way that they work. Also, we will look at their complexities. See a few ways to sort an array or another data structure that you might have. 15. Bubblesort: Hello guys and welcome back to lecture three. In this lecture, we will talk about the most basic algorithm that sorts an array that you can implement by yourselves very easily. It is called bubble sort. It doesn't have the best time and space complexity. But we'll get to that in a second. First of all, I have to say about this algorithm, besides the fact that it's the simplest sorting algorithm exists, how it works is by repeatedly swapping the adjacent elements if they are in the wrong order. So now let us look at this example so we can visualize better than by looking at the code. How is the way that the algorithm is actually white cell? We are going to take the array 5142 into what it does. Basically paid first two elements. And it sees that five is bigger than one, so it swaps them. Then it takes 545 is also bigger than four, so it swaps them again. Next, 525 is bigger than two, so it swaps them. And at the end we have 58. These are correctly position, so it doesn't make any swaps. Then it passes again. Taking elements two-by-two, as I've already said, adjacent elements, paraphrase them if they're in the wrong order and if they are, swaps them, if not, it doesn't. One in four are in the correct order, so it won't swap come for him to or not in the correct order because four is bigger than two, so we will swap them. 45 are in the correct order and then 58 are in the correct order. Again. You can see at this point our array is already sorted, but our algorithm doesn't know if it is completely sorted yet, because it could have not at this point. So it needs another hope is that it won't swap obviously any elements because they are already or third sending. But as you can see in the third base, it takes again the elements Dubai, and it doesn't make any swaps. Now, let's look at the code for this algorithm. As you can see in the main function, we are declaring is usually a hard-coded array with some values in it. Next we declare an integral, and this time to eat the size of our array that we declared, making use again at the size of operator. And then we are calling the bubble sort function. That as you can see, it takes two parameters, our array, and it's now moving up in stack. You can see that it enters the bubble sort function. It returns a void because it just sorts the array and doesn't return anything. For the first element takes the array in this, I've said, the second element is the size of it. Now we will declare two elements, I and j. Theta. I'm just used to iterate through the array. It goes like this. Query. Each element of the array, we will go again from 0 to n minus I minus one. You can ignore because it is zero-based. It basically goes from the first element of theory to the n minus item. And then it checks if ARR of j is bigger than ARR of g plus one. Which means that we have a bigger element that is before a smaller element. And we cannot have this SP1 to our array in ascending order. Swap the addresses of elements located at, before said indices. Display making the change pregnant. And when we return to print the theory, you can see that when we run the program prints the sorted array increasingly with the fact that the second loop on the iterates to n minus I. There is a reason behind that. Because the array elements after n minus I already sorted. Because if we think about it, first, it goes I goes from 0 to n minus one. So the end of theory in the second loop goes from 0 to n minus I minus one, which is also n minus one. So it goes to the end. It keeps the chance for the last element to be at the last position. Next, iterate from 0 to the last element. And then the chain element will iterate on the two n minus one minus I, which will be one, that's n minus two. So excluding the last element. Basically it will search the second biggest element from the array and so on. That's how the algorithm works. It continuously thirties, where the biggest element to put it at the end of theory. By the end, I understand the end is not already sorted. The first iteration, it will search for the biggest, biggest element. The second iteration for the second biggest, and so on, reaches the first element in the array is already sorted. If we were to talk about the time and space complexity of this algorithm, the space complexity is linear in regards to the input because we just declared this array right here, and then we declare two variables, iterating three, but that are considered constants. So the space complexity is big O of m and it is linear. Now getting to the time complexity of this algorithm is big O of n to the power of two. So it's a quadratic time complexity as the algorithm iterates for each element of the array. Another iteration to basically not really to all the ray, but you get the idea. It tends asymptotically to a quadratic complexity. Now again, we have a swap function that I didn't even talk about. What this does. As you can see, it doesn't return anything it takes to integrate pointers and it swaps between them. That's a very quick and simple sorting algorithm that you can use on a race that you wanted to sort English increasingly. But just know its time complexity is quadratic and not the best type of time complexity that you can have when sorting an array, which would BASF already said n log n. So if we propose to implement this algorithm now that it's not this time complexity, as you can see in the next lecture, there are better sorting algorithms out there that you might learn and actually implement during your interview when being asked about it. But it's a foundation. And this is a pretty basic algorithm. It's nice to first make contact with an easier sorting algorithm to get it started. 16. Quicksort: Guys, welcome back to lecture four. In this lecture we will talk about Quicksort. Quicksort is another sorting algorithm that works on arrays. And it's more efficient algorithm then propose sort From the time complexity and space complexity point of view. Now, unlike March toward, quicksort is a divide and conquer algorithm. What it does, it just big element and partitions the given array around the pivot. Many different versions of quicksort, that big pivot in different ways would be to always pick the first element is. Another way would be to always pick the last element, this pivot, as we will do in our implementation. You will see that in a second. Then you can pick a random element is period. The best way would be to pick the median SPM it. The key processing quicksort is partition. The target of partition. Given an array and an element x of array pivot. What this partition function does is that it puts x and its correct position in an array, meaning that all the smaller elements then it would be on its left. And all the greater elements then it will be on it, right? On this process should only take linear time complexity. We look at the code and try to understand it. We are going to see that in the main function we declared an array as we always do this hard-coded values. Then we take its length using the size of operator. And then we call a function called quicksort that takes three parameters. The first parameter being the array. The second parameter, pink dots over bound to that you want to sort, in our case, first element index, that being 0. The last element, that third parameter, the upper bound that you wanted to sort in our case, the last element index, and that is n minus one. We also declared a couple of oxygen carry functions. One of them printing theory. The second one is swapping two elements using pointers. Now, if we go to the QuickSort function that gets called from the main function, we are going to see, first of all, checks if low is smaller than this is done because later we will recursively call this function in the left and right subarrays of the pivot. So we always need to keep that in check that the lower bound is lower than the higher bond. Then going to give the value of perdition of our array. And lower and upper bounds being the partitioning index. Meaning, where is our pivot at the right position in the array that would be sorted. In this deposition that we just talked about. The position where all the elements in its left and smaller than him, and all the elements in it's bigger than him. It doesn't matter what their order is because the array sorted or not. It doesn't matter. That element is at the track position where that condition happens. And then we will recursively call this function our array, the low bound and pivot position minus one. And then our array pivot index plus one and then higher bound, meaning that we will recursively call quicksort for the left sub-array and the right subarray of the pivot that is correctly positioned at this point. Let's see what this partition function does. It also takes three parameters as the QuickSort function does. We declare a pivot. Integral takes the last element because as I've said, we will implement the variation of QuickSort where the pivot is taken as the last element from the array. Then we will declare I, which would be o minus one, minus one, because the first element of our array would be 00 minus one is minus one. We will see in a bit why we take it minus one and not 0. And then we will use another integral to iterate through the whole array. Iterating through the whole array. We say if ARR of g, meaning the current element from the iteration, is smaller than the pivot. First we will increment I, then we will swap ARR of I of j. Then we will move on these dyes, linear iteration through the array. And 28, we're finding an item that's smaller than our pivot. In this case, the last element of the sub-array we are at it, we'll put it in the beginning of the array. In the beginning, well, first index that's not already occupied. It puts all the elements that are smaller than our pivot in the front of the array. Then lastly, we will swap ARR of I plus one with our pivot. Because that's its right place in the array. That's where it would be wrong if the array will be sorted, we will simply return this index, that would be its correct index. Now, you can see we understood how the partition function works. And we also understood that after cold, we also called recursively this partition function on the left and right sub reason to pivot. This way, sorting the array. Now as you can see, we have an array of elements then 789, One, and five. When we run it. The printArray function should print our array. This, you can see these sort data. Now let's talk a bit about these algorithms. Stability respects are not in place. Property. First of all, is Quicksort stable? The default implementation is not stable. However, any sorting algorithm can be made stable by considering indexes as comparison parameter. Second of all, expert, the broad definition of in-place algorithm. Quicksort qualifies as an employee sorting algorithm. C2c is extra space only for storing recursive function calls, but not for manipulating the input. We can say that it has linear space complexity. Let's talk about the time complexity to really see how efficient this algorithm is. Well, even though it's better than bubble sort, which in the best time complexity would be linear. But in the average and worst cases would be quadratic, would be big O of n to the power of two. Quicksort pattern in the average time complexity, various n log n. The mask complexity is still n log n, but the worst complexity is still quadratic. N to the power of two. In interviews, name actually asks you something about weeks. If not the full implementation. You may ask you if you know what its time complexity, whether you know how to partition function works and what's its time complexity. Which by the way is linear. As we already saw. We only iterate through the array. And he might even SQ the recursive calls in quick sort function where it is a very good sorting algorithm in an interview. And it's a very useful tool you can use to sort the elements of an array that you have. When you don't have the STL sort function, bubble sort, bubble sort. If you would want something more efficient, then this algorithm would be a perfect match. 17. Trees: Hello guys and welcome back to section six of this course. In this section we will talk about the new data structure called threes. And unlike arrays, linked lists, stacks, and queues, which are linear data structures, trees are hierarchical data structures. The top node is called root of the tree. The elements that are directly under an element are called its children. D element directly above something is called its parent. For example, a is child of f and f is parent of a in this tree debt we drawn on the screen, right? Finally, elements with no children whatsoever are called leaves. Now let's talk about why would we use trees? Well, one reason would be because you went to store information that naturally pharmacy heirarchy. Think about how your files are organized on your PC or Mac book, whatever you have, the start from the root folder and then you go through them in an article order. Fast system on the computer. These probably implemented using trees. Also, trees provide moderate axis and search. That is curtain linked list, but slower than arrays. Tree is also providing moderate insertion and deletion. Quicker than arrays but slower, thinner, unordered linked lists. Also likely list. And unlike arrays, trees don't have an upper limit on number of nodes. Nodes are linked using pointers. So there is an advantage when we look at this page that a tree and you can store. The main applications of trees include manipulating hierarchy TO data, making information easy to search. We will see that it traverses, in one of the next lectures. Manipulate sorted lists data. They can be used as a workflow for composing digital images, for visual effects, router algorithms. And also the farmer multistage decision-making, for example, business chess. From an implementation point of view, the tree is represented by a pointer to the topmost node in the tree. The tree is empty, then the value of this topmost node called the root is known. A tree node contains following parts. First of all, it contains data in, then it contains pointers to its children. We can represent three nodes using structures. For example, I'm attached right here. You can see exactly what I'm talking about. But we will move on to implementation in C plus, plus that little bit later. Right now let's talk a bit more about what types of trees there are in programming. As I said, three in computer science is like in the real world. The only difference is that in computer science it is visualize this upside down with root on the top and prevent disease originating from the root to the leaves of the tree. Tree data structure is a non-linear data structure. A tree can be represented using various primitive or user-defined data types. As we saw with discharger just now. Implemented three, we can also make use of arrays, linked lists, glasses, or in other types of data structures. It is a collection of nodes that are related to each other to show the relation nodes are connected with edges. But in practice, more like heavy pointers to one another. The types of trees in data structures. First of all, there exists the general tree, which there is no constraint for it, imposed on it, on the air kept the tree. In general tree each node can have infinite number of children. These three is the superset of all other types of trees. Now, we will move onto binary trees that are much more useful in March, more about interview questions just because they have more simple and elegant structure and are easier to form questions based on. The binary trees is the type of tree in which each parent can have at most two children. The children are referred to as the f chart or a right child. Ntc is one of the most commonly used trees in certain constraints and properties are imposed on binary trees. It results in a number of other widely-used binary search G AVL tree. So on. We are going to talk about these types of trees right now. So binary search tree is an extension of the binary tree that we just talked about, but it has some other edit constraints. For example, the value of the left children of a node must be smaller or equal than the value of its parent. And the value of the right channel is always larger than or equal to the value of its parent. This property of the binary search trees make it sit suitable for searching operation. Intense. As it each node we can decide accurately whether the value will be in the exit to your rights. Therefore, it is called Search Tree. More complex type of tree is the AVL tree. That these are self-balancing binary search tree. The name AVL is given on the name of its inventories. Adult son felt shy. Then this is the first dynamically balanced tree that was ever implemented in APR tree. Each node is assigned a balancing factor based on which it is calculated whether the tree is balanced or not. If you have tree, the height of children of node differ by at most one. The valid balancing factor in if the arteries are 10 n minus one. When the new node is 80 to the AVL tree, entry becomes unbalanced, then rotation is done to make sure that the tree remains balanced. The common operations like look-up insertion intuition takes only logarithmic big of time in these AVL tree and it is widely used for lookup operations. There also exists some trees that are called the NRV trees. The maximum number of children they can have here is limited to this variable n. Binary tree is a tree, as you denote in binary today's most two children tree data structure, you find that the most common used in presentation of n. But full NRA trees, which children of a node is either 0 or complete enter retreat is the tree in which all the defaults are at the same level. For some properties of binary trees. Some more mathematical properties. We can say that the maximum number of nodes at level l of a binary tree is two to the power of l. Then again from its construction, the maximum number of nodes in the binary tree of height h plus two to the power of h minus one. In the binary tree with n nodes, minimum possible height or minimum number of Cs logarithm of base two of n plus one. Let's do a binary tree with LDFs has at least two l plus one variables. Also in binary tree where every node has two children, the number of leaf nodes is always one more than nodes with two children. This is a broad overview over the tree data structure. These are very useful in interview questions. Is the come up into more complex topic to discuss here. Many people I know including myself in the best was not so short on trees. But in this course we will look on some exercises with them, traversals and so on to make you feel more ready for your coding interview. Especially on these data structure. Then two problems do people, people who have been interviewed in the past. So let's move on to the next lecture now. 18. Traversals: DFS, BFS: Hello guys. In this second lecture, we will talk about tree traversals, more specifically, binary tree traversals. As you already saw. Unlike linear data structures that are arrays, linked lists, queues, stacks, etc, which have only one logical way to traverse them. Trees can be traversed in different ways. Following are the generally used for traversing the trees. We will talk about depth first traversal, this lecture, which are in order, meaning first we go to the left, note, then the root, and then to the right node. Pre-order, which is we first visit the root, then the left child and right child. Let's say we have postorder, meaning we first go left, then go right, and then lastly we go to the root. There are also ESA, breadth-first traversal or level order traversal, which basically takes, prints the note in order of their levels, of their layers. The in-order traversal algorithm would be to traverse the left subtree first, then call in order for the left sub tree. Then visit the root tendon, traverse the right subtree, and then call in order for the right sub tree. In order one, again was first we visit the left child and right child. Uses of in-order. In case of binary search trees. In order traversal gives nodes in non-decreasing order. To get nodes of a binary search tree non-increasing quarter of variation of inorder traversal. Inorder traversal easily can be used. The preorder traversal is pretty similar to the in-order one except the way we do things. So first we would visit the root end towards the left sub tree and called preorder of the lips. Leslie, we will traverse the right subtree. Preorder. Postorder traversal would be first traversing the left subtree, call postorder of left sub tree, then reverse the right sub tree and call postorder of it. And thus, we would visit the root. You see some preorder traversal would be to create a copy of the tree. It is also used to get prefix expression on an expression tree. Post-order traversal would be used to delete a tree, would be also used to get the postfix expression of an expression treatment. If we were now to look at the code that would do these depth-first traversal. First thing, the main function, we will declare the root, note this down using a struct that's called node, and we declared it upward. We have an integrated host the data and then two pointers to the type note that's left and right children. And also a constructor that takes an integral test data, then initializes the children of these nodes to know. So we'd say leaked or not definitely, but just to note it, no children. First we declare a root and then we give it left. And you know, if two bitrate note of three, these are just failures, meaning no two failures. And then left, left we have a node with the value fluorine though they've tried to be a noted the value of five. This right here is how our tree would look. And then we call pre-order, in-order and post-order of these functions takes one argument, that's the root node, for example, with the post-order. Notice don't know, obviously, we will recursively call for the left children, then for the right children, and then we would print the data. So what this would do is it will recursively called left until it arrives to the leaf. Then it will return from recursion and takes him right. Then finally some root value. Then you also have in-order, pre-order already set. Just the difference, only a difference in succession of these instructions exists. In order. Again, check if the node is not null because if it means you're already finished the tree or there is no children there. We then call recursively the function for the left node. Then we will print and then we will recursively call for the right. The pre-order. Obviously. We check again, need to know these nano. First we print, then call recursively far left. And then for talking about the complexity of these algorithms, well, come to the stage. For all the problems are actually server-side pleasing volt because basically iterate. Note. And the auxiliary space, if you don't consider the size of a state for function calls, then it's constant, we go one. Otherwise it would be linear big O of n. Now let's talk about level alter binary tree traversal, which is breadth-first traversal. So there are different methods. We will talk about the method that uses a function to print a given level. Again, largely tried to do here is print the number of nodes in the level order from left to right on levels. For example, for the last tree that we saw, the level order traversal for it would be 12345. The algorithm here would be to implement two functions. One is to print all nodes at a given level, so we give them an apple. The other function is to print level order traversal of the tree. Level order makes you the print keep on levels to print notes at all levels one-by-one starting from the root, we would do is first print level order of three. Go from one height of the tree and print that level. Iterate through all the levels and call print given level. Let you take two arguments, the tree and that level, and print it. The print function, print given level. We check if the tree is known, then it would return. If the level would be one, then it would bring to the world. And it would recursively call been given level of the right and left tree with level minus one. As you can see right here, we made the function to create a new node function that would return the height of the tree. The two functions that we talked about. As I said, the print level order function takes the argument, the root. Then we'll calculate with the height method the height of the tree. Iterate throughout the height and coping given level of root I, which is the number of the level we are on currently. And pink given level is a function that takes the level and note checks if the root is null. If it is, then it will return. If the level is one, it will print the root node. Because if we are on the first level, it means we are at the roots, we would just print it out recursively calling anything. But if we are on a lower level, I'm not the root level, but downloads, we will recursively call this function for the left and right. Note with the level minus one. Hence the second parameter. So I think that's pretty straightforward. Again, you can see for the tree that we showed on the screen, the level order traversal is 12345 is we already figured out. Again here. Complexity for this algorithm is linear. Here regards to the time complexity big O of n, as we iterate through all the nodes once recursively, DC is pretty much the ways you can traverse binary search tree. And they are very useful to know because they will give you more morbidity in a tree. And they will make sure on your sales when dealing with three question on a coding interview. So now let's move on to the next vector. 19. Check for children sum property: Hello guys and welcome back to this course. In this lecture, we will talk about the three problem that sometimes can appear in an interview question. That is to check for children some property in binary tree. What that means is that given a binary tree, you should write a function that returns true if the tree satisfies the property that for every node, data value must be equal to sum of theta will use in left and right children. Consider data value is 0. For now children. For example. If we would have a tree that would have the root, then the left children would be eight and the right children would be two. That would be a valid tree. And so on below, if that child with need to have two children, so left hand try at least that their data in some should equal eight, and so on for the entire tree. The algorithm that we are, we'll approach here is to traverse the given binary tree. And for each node, we should check recursively if the node then both these children said is by the children some property. If so then true else return false. That is pretty straightforward. Let's not jump into the code and see how can we do that on a more specific technical level. All right, here we already declared some stuff that would help us with the implementation of the tree. So we declared a structure that's node. And then we declared an entire tree is some property of root two. Then we will print that the condition is satisfied, otherwise false. So we basically we are going to implement a function that's called East some properties. It takes the parameter the root node and returns an integer, which might as well have been a Boolean, is the same thing because if you either return 0 or one, then jumping into this function, we declare two variables auxiliary that will help us remember the right and left values of the children of the node that we are at the present with the iteration. Then if the node that we are honest or its children or no, then we will return one. Because that means we've reached the end and it's okay because everything checked out to be true up to that point. Otherwise, you will also see that the majority of these algorithms start with the base case of this tree algorithms. First, our recursive and second, start with the base case, meaning the ending case. Well, we have multiple scenarios here. If the left node is not null, then the data in it, so the number that it holds will be given to the left beta integral that we declared here. Then again for the right node, we will do the same thing. And then we will check if the node data, so the number that the node we are right now with the iteration is equal to the sum of the left and right children. And also recursively called the same function for the left node and the right node. We will recursively check the same thing for both of the children of the node. Then we are going to return one, meaning it's true. And our three 0s, with this condition that we are checking, else we will return 0. So what this does is recursively call by using the cost stack. And when it will return from the call stack, it will hit this one. If all the ECM properties will return true, as you can see right here with the end statements, all of them needs to be true in order for this if statement to check out and return one. This is how we will check this condition in all of the tree with a recursive function. Now talking about the complexity of this algorithm, as you are going to see in almost all the tree algorithms. Linear from the time point of view and constant from this base point of view ways we only declared two integrals. But from the point of view, iterate through the entire tree. So that's linear big O of n. Thank you guys for sticking to the end with me on this tutorial and I will see you in the next one. 20. Sum of all the nodes: Hello guys and welcome back to this course. In this lecture, we will talk about another tree problem. Let's give them sometimes in calculating the sum of all nodes in a binary tree. I think the title is pretty self-explanatory. What you would need to do when given this problem is to provide an algorithm for finding the sum of all elements in binary tree. Basically, you need to summarize all the integrals that are held by all the nodes in a binary tree that's given to you. As usual, we will approach this algorithm with recursion as we usually do in three problems. Let's look at the code to see how we would do this problem. We declared a struct. Note that keeps him inductor is the key and also the node's left and right that are kept. By giving them a pointer to the node structure. We drew a tree right here. And then we declared by some integral and we assigned it our function call that's supposed to return the integral. That integral being the sum of all the nodes in the given tree, T only parameter that this function takes is the root node of our tree. Pointer to the node. Obviously. It goes like if root is null, then we should return 0. As usual in three recursion algorithms and methods, we start with the base case, meaning what happens when the bottom call these heat? When root is no, we reached the end. So there's no note anymore because we recursively call this function until we run out of nodes. If that's not the case. So if we didn't reach a route, we should return the root key, meaning the value that the root is keeping inside the because you can see the structure, the key is the integrated that node holds. We also add the recursive course of this function for the left and right child of the root, meaning the note that we are on it. The current call, of course, recursive the dish will be called for the left children. And then again, the execution was started with no return. 0 IS return its value and then again recursively call for each of them. I think you understood how this goes. Now we're talking about complexity of this grabbed row. Well, the time complexity is linear as we iterate through the whole tree is pretty intuitive that we need to iterate through each node so we can find out what value it holds true to ourselves. And then the space complexity is constant as we do not declare any elements other than the standards of Carsten sold yet it's big O of one. Thanks guys, and we will see each other in the next lecture. 21. Check if all the leaves nodes are at the same level: Hello guys and welcome back to this course. In this lecture, we will talk about yet another three problems that might be given into an interview environment. That is to check if all the leaves are at the same level in a tree. In this problem, we'll ask you to do is given a binary tree, you just need to check if all the leaves nodes, meaning the nodes that don't have any children. So the ones that are at the bottom level, at the same level or not, basically imagine the root being on level one, immediate children being on level two, and so on. Until you find the leaf level, it has usual, we will approach this algorithm using recursion. Now, the idea is to first find level of the leftmost leaf and store it in a variable. And we will use that variable. Then compare level of all other leaves with debt level. If it's the same, we will return to end otherwise false. We traverse the given binary tree in a preorder fashion. The level that we keep in mind, we'll be best to all the calls as an argument. The value of this argument is initialized with 0 in another function to indicate that, firstly, if he's not yet seen, the value is at the plane. First find a leaf or level of subsequent leaves in pre-order is compared to this level argument. Now let's take a look at the code. We declared the node structure and the constructor for it. And in the main function, constructed three for us. And then we have a function that's called check that takes the root of our tree. And what it does is that it initializes level in leaf with 0 and returns the code to this check, a function that takes as parameters the root of our tree, then the level and leaf level that are both initialized with 0. As you can see in this check until function. The base case is when we have a root, that's now. And then we should return true. Then the children of the node that we are right now are both null. It means that we arrived at a leaf node. And then we check if it's the first time when we arrive at the leaf node. How we do that is by checking if leaf level is 0, as you can see here, he's passed by reference, so the value of it remains. The one when we call the leaf level is 0. It means that it's the first time when we encounter a leaf, we assign to this leaf level, the level that we are at right now. Furthermore, if we don't enter this if statement, we then return level equals to leaf level. What this means is that we are right at leaf. What is now the Firstly, if we are right that we should return whether the level is equal to the leaf level. The leaf level is the actual level of the first leaf we arrived at. All our leaves needs to be at the same level. That's why we keep in mind this variable right here. Then exiting this if statement, meaning if it's not a leaf that we are at, right now, we return recursive calls of this function for the left and right node. Because we are right now at the node that's not a leaf and Xist, which means we are at a parent node. We need to recursively call this function for both of these children and increments the level. Also, while keeping in mind the leaf level, it's the bottom most level of the first leaf we ever encountered. As I've already said, I will stress this. Again. We remember this leaf level debt, the level of the first leaf that we have encountered. And this is the reference that we will check. Furthermore inode next leaves that we will encounter for the complexity of this algorithm. Again, the space complexity is constant. This we do not use any additional space bigger of one. And then the time complexity is linear. As we traverse the entire tree to find firstly, the level of the first leaf and then checking all the other leaves to have the same level at the first leaf that we encounter. Thank you guys for watching this tutorial and I will see you in the next section. 22. The balanced brackets problem: Hello guys and welcome back to this course. In this lecture, we will talk about the problem that's very often given in an interview question. That is to check for balanced brackets in an expression using a stack. Well, that's done using a stack, but the interviewer might actually not deal. You get this problem done using this taken tonight, figured that out for yourself. The problem gives you a string. That's an expression, and you need to write a program to examine whether the pairs and the orders of the brackets, correct in that expression, the parentheses can be currently normal or squared. For example, I will put on the screen right now two different inputs. So you can see that the first one is balanced and the second one isn't. You cannot close the square bracket before closing the normal one because there is not the natural order. What the algorithm would be to declare us deck that holds characters and then traverse the expression that you are given this string, basically iterate through it. In dendrite two scenarios. First one, if the current character that you are iterating through at that moment is starting bracket, Start normal bracket, starting curly bracket or starting squared bracket, then you can push it to this deck. The second scenario is if the current bracket that you are currently on right now with iteration is a closing bracket. Again, a closing normal brackets, closing square bracket, closing curly bracket. Then pop from this deck. Right now you are pumping the top element and you are going to see what is the last open bracket. And if the pop character, so the last open bracket is the matching starting bracket, then it's okay. The brackets are not balanced. So after complete traversal, if there is some starting bracket letting this deck, then it's not balanced because in our string there exists opened brackets that I have not been close to the end of the expression. Let's look at the codes right quick. We have a main function and read exert an expression that goes like starting curly brace, starting curly brace, starting normal brace, ending normal brace and the curly brace. So that is okay. Then starting squared bracket, ending squared bracket. This should be a balanced expression because there are not any brackets that are left and opened or closed in the wrong order. Now we have a function called, we declare the function that's called our brackets balanced that we are going to see it has one parameter, that string. We declare a stack, as we already explained why that holds the type of data char. Then we declare an auxiliary chart called X. For int i from 0 to the length of the expression. We iterate basically with this loop through each character of the expression that is given. We take each character one by one and verify what type of bracket these. First, we need to see if that bracket is currently squared, are normal and it is starting in type one. If it is, then we can push it in our stack and then we continue as we don't need to go forward with the rest of the loop execution. Otherwise, if it's not starting bracket, we can check if the stack is empty. And if the stack is empty, we should return false. Because it means that is a closing bracket. Is it cannot be starting bracket because if it would have been, the execution wouldn't be right here, right now. It's a closing bracket and the stack is empty. What does that mean? That means we have arrived to a closing bracket that has no matching starting bracket before it. So it's not a valid expression of parentheses. If that's not the case, we have a switch statement based on the character that we are right now in our expression. So we have different cases. The case when our character is a closing normal bracket, we are going to. In our auxiliary character x, the top of the stack. And then we will pop the top of the stack as we don't need it anymore. And then we are going to verify the value that was in it. If the value that was seen, it was a starting curly bracket or a starting squared bracket. Then we should return false as we arrived to an ending normal bracket and list one that was open, so it's matching bracket was not the same type that EDs. And then we should break. In the other cases, if it is a curly bracket that is ending, and then the starting matching bracket is OK. The other two types, It's not okay, so we should return false. Then again, if it's an ending squared bracket and its matching parenthesis is normal or a curly one. Again, it's not a valid expression, so we should return false and then break. The same procedure also applies, where we put in our auxiliary character the top of the stack, and then we pop it. When we are done with the iteration that our stack should be empty. So there should not be any parenthesis left opened, because that means they don't have any ending parenthesis that are matching. If the stack is emptied means that all the markets have matched. And the expression is valid. If the string is not empty at the end of the execution, that means that there are some elements in it. And as you already saw, we only push in it starting types of brackets. And that means that in it are left starting brackets that have no matching ending brackets. And that means that's not a valid expression. So this function is called in an if statement. So if this function right here, meaning this function is returning true, we can return that the expression that we are given is a balanced expression. Else it's not balanced. So as you can see, knowledge sample, if we run the code, you can see that it says balanced, so it's balanced expression. Now let's talk about complexity of this algorithm. The complexity of this algorithm from a time point of view, this linear as we iterate through our expression one time. So that's big O of n. Now the space complexity is also linear as we declared a stack that can hold as much as the whole string. In the worst-case scenario where the string contains on starting brackets. You can do this in a more efficient way where you don't even remember this deck. And instead of this deck, you can remember some numbers. For example, some variables that you increment when you meet a starting bracket and decrement when you meet an ending bracket. That's a more advanced solution. It you might try at home or search for it. But the basic solution for these problems, this one and this one you should really understand and know by heart. But thank you for sticking with this tutorial to the end. See you next time.