 What's up guys, Mike the Coder here. Today we are going to go over another lead code problem. So we are just mostly going to go over Google interview questions. I'm pretty sure like this is, I'm not sure if like these questions are actually blacklisted or they'll actually get asked on Google, but I've heard it's probably very similar, but yeah. So we're going to go over these problems and this is one of the first most frequent problem on Google interview question. This is shortest path in a grid with obstacles elimination. So yeah, so you're given this grid of M by N matrix. So it's like a board, right? It's kind of like a board here. And we're going to start out the upper left corner at zero zero. And then our job is to move to the bottom right. So we're going to go from here and we're going to move to the bottom right down here. Okay. So yeah, we start here and we're going to go with bottom right down here. Now, we basically what we could do is that there are obstacles inside this board. So in this board, there's like some of these brick walls and in these brick walls, you can't really go to them, right? You can't really go through them, right? So you have to go around them, right? So we're at the top left corner at zero zero and we want to reach the bottom right corner. And there's some obstacles here. Now you can remove at most K obstacles. So if you want to walk from the top left corner to the bottom right and let's say the K is equal to one here. So let's say K is equal to one. So in this case, if K is equal to one and I can remove one obstacle from my path and let's say I want to move from here to the bottom right corner, go this way, right? All the way down and then to the right. Then I could do that because I could just remove this one obstacle from my path. So I just go down and I remove this and down, down, down, down and then go right, right? So then I would be able to go from the top left corner at zero zero to the bottom right corner. Now, so yeah, we can move at most K obstacles. Now what the question they want us to do is to return the minimum number of steps required to walk from the upper left corner to zero zero to the bottom, bottom left corner. So from this top left to the bottom right, our job is actually to return the minimum. So the minimum steps required. So like, yeah, okay. So let's just go over some K scenarios just to make you guys understand the problem a little bit more and then we could just go over go over what it actually means. So let's actually just take a picture and let's actually go to like paint and I can show you guys what this means. So why is this problem labeled hard? Because depending on your K, you might not actually be able to reach it, right? So let's say, so here's the board, right? This is like a given board that they give us. It's random, right? In the first test case. So if K was equal to one, so let's just go back to the same situation I was saying earlier. So if K was equal to one, right? That means I could remove one obstacle. So in our early scenario, right? We're starting from here and we're just gonna go down and then we remove this obstacle. Okay, so it's K is equal to one. So this would be like gone and this would just become white. So this is gone. So we could go through here now after it's gone. So I could just like remove this technically. I just go here and remove it. Oh yeah, I need to select like this. Okay, so I go here and I just remove it. So when I remove this obstacle, that means I could go to that spot in the location. So if K is equal to one and I removed one obstacle, right? Then my K would be zero right now because I can't remove anymore. Now, yeah, because now K is equal to zero, right? I can't just remove more obstacles anymore because I don't have any more obstacles. I don't have any more K left to remove. I only can move at most one. So in that case, I could just go down, right? And then there's a pretty good path here already. So this would be like one step to go down. And then another step to go down, so it'd be two. And then another step three, another step four, another step five, and then another step six. So the minimum steps it would take from reaching the top corner at zero zero to the bottom right corner. So to the bottom right corner here, starting from here, it would be six, right? Because I started from here, I removed one obstacle and I went one, two, three, four, five, six. Okay, so that would be like one, like this would be the answer for K is equal to one. Now the question is pretty hard because let's say if your K was equal to zero. So let's say I can remove zero obstacles. So I can't remove any of them, right? So in this case, since there's too many obstacles around here, I can't actually go, I can't remove the one below me, right? So in this case, I would actually have to like go around all the obstacles. So I have to go here, one, two, three, four, five, six, seven, eight, nine, 10. Right, I would have to go, this would take maximum of 10 steps, minimum 10 steps, right? Because I can't remove any obstacles around me. So it'd be 10 steps. And the reason why is because I can't remove any obstacles around me, so I have to like go around and to reach the bottom right corner at this location. Okay, so yeah, I hope you guys understand this problem. And yeah, that's basically the problem, why, what makes this problem hard? That you only can remove K steps. Not K steps, K obstacles, okay? So yeah, so there's like many ways to do this problem. I'll just go over the solution now with you guys because it's not super-duper bad. So what we could do is actually just do something called, we're just gonna run breadth-first search. So what that means is that if we're starting from here, right, we're just gonna go to our surrounding locations and visit them. So yeah, we would just like visit this spot, this spot, right, so we'll visit these surrounding locations. And what we're gonna do is we're gonna actually maintain states corresponding to which spot we visited. So what we're gonna do is that we're gonna have like, we're gonna push, we're gonna maintain states each time we visit something. So anytime we visit something, we're gonna increase the steps, right? So the first thing we need is the steps or the number of steps, right? Because anytime we visit a surrounding location, we need to add, increment the number of steps, right? Because the problem is asking us the minimum, what is the minimum steps required to reach from the top left to the bottom right? So we need to keep track of the steps. Like that's just what we have to do because if we're gonna go move any way, we have to like keep track of it, okay? So the number of steps, we're gonna increase it by one every time we go to our surrounding location. So what we're gonna do is run breadth-first search. So we're just gonna visit all our surrounding locations here, right? And then we're gonna increase number of steps every time. So remember, we're gonna add one to steps every time because every time you go down, move away from your initial spot, you need to add one to your steps. Okay, the next thing what we're gonna do is we're actually gonna decrease the K. So we have K is equal to like one in our current situation, right? So anytime we actually see an obstacle in our path, we need to just, we need to remove, like decrease our K, right? So like if we were at this bottom, at this bottom spot, right? So let's say I visited this spot and yeah, since there's an obstacle in there, I would have to decrease K by one, right? Because we only could remove certain number of obstacles from our path, right? We only have most K obstacles. So anytime we visit an obstacle, we'll remove K, okay? And another thing we need to keep track is are the spots that we already visited. So to do that, what we could do is we could just have like a completely separate board representing the different spots that we already visited. So anytime we visited something, we'll just like mark it as something we visited. And then yeah, we'll mark it as something we visited and it'll just be like the certain row and column. So if we had like in this situation, let's say we visited the one, the cell across us, right? So in this case, the cell is at row zero, right it's row zero and column one, right? Because it's like indexed from like zero, one, two, right? Because it's indexed from like starting from zero. So zero, one, two, zero, one, two, three, four, okay? So yeah, and that's that part. So then what we're gonna do is we're gonna have like a completely separate board and we're gonna just mark it every time we like come across something that is not visited, right? That we is not visited and we just visited. So if we have a separate board like this, it would be like zero, one, two, three, four. It would be four rows and three columns, right? And what we're gonna do is if we visit the cell right next to us here, we'll just mark it as visited. So in this our new board, we'll just mark it, hey, that's visited, okay? And then when we reach to the end cell, the last cell on the bottom, what we're gonna do is we'll just return the minimum number of steps that we've finally reached to. Okay, so that'll basically be the gist of the code. Okay, so to run breadth-first search, we're not gonna use recursion because this is kind of harder to do if we're just gonna like push like a lot of these things. So what we're gonna do is we're gonna maintain a queue, right? So if you recall, breadth-first search is a queue, depth-first search is a stack, okay? So what we're doing is we're gonna push the surrounding locations that we're visiting of our neighbors onto our queue. And each of them is gonna be able to have like its corresponding, so we're gonna push like the right side, the bottom right here, these surrounding neighbors and their positions and the current step and the K onto the queue. And yeah, that's what we're gonna do. And then every time we're gonna like pop each spot from our queue and then we're gonna increment the number of steps and then in the end, as we finish our breadth-first search, we're gonna just return this minimum number of steps, okay? So yeah. And yeah, so. Okay guys, so I'll show you guys the code now and it's really not super hard to understand if you actually like get what I was talking about. So here we have the first line of code is about a visited 2D visited board. And it's just an integer board that is exactly the same thing as grid. And we initialize everything to be the same size as the grid. So this is like the first parameters is the size of the grid. And then here is like the number of columns size of the grid also. And we're actually gonna set them equal to negative one first because visited for all them values that are not visited yet, we're gonna set it as negative one, okay? It's just easier this way, okay? And then here we're gonna have our queue. And our queue is representing as a vector of four values that we're gonna keep track of, okay? So this is a queue. It's gonna be the structure that holds all the, the structure that holds allows us to run breadth-first search to go through all the values, okay? And this is gonna be a vector of integers, okay? And we'll just call the queue queue, okay? Okay, so this is the first part. The first part is that we're gonna push the X, Y coordinates every time we're at the queue, right? So the first part, we're gonna push the X, Y coordinates and we're gonna also have the current number of steps, which is like the current path, which is gonna be zero also. And then we're gonna have the number of obstacles to remove, which is gonna be our K, right? So in our queue is gonna have like four values in it. So our queue is gonna be like, our queue is gonna be this data structure that every time we visit a certain spot in the cell, we're gonna push the row, the column, the number of steps and the number of Ks to remove. So if we go back to our drawing here, so since we're running breadth-first search, right, we're gonna have this. So let's say we're starting at zero zero, right? So our queue is gonna be like, this is gonna be like our queue, okay? It's not really represented like this, but bear with me, it'll be like this. And then the queue is kind of like, a queue normally is a data structure that has like a line. It's more like a line, right? But yeah, we're gonna push four values. The four values are gonna be like an array. So this is what we're gonna push. We're gonna push like the row, the column, our current number of steps, right? And then the value of K every time. So in the first part, before we start anything, we're gonna push zero zero, because that's the row column at zero zero, row and column at zero zero. And the reason why for that is because we're starting at the top left corner and we wanna reach the bottom right corner. So that's why we're pushing zero zero, because zero zero is our starting row and column where we're at. And the current number of steps that we are starting is gonna start from zero because, I mean, we're not adding any number of steps, right? So that'll just be zero also. And then K is just gonna be like, K with like whatever K value. So now that we, this is gonna be like the starting point of our breadth first search. So before we even do anything, we're starting at zero zero and we're gonna have all these values here, okay? Then what's gonna happen is we're gonna pop this the first part of whatever is in our queue. So we're gonna pop this. So this is gonna be like popped out, right? So this is gonna be removed. And then we're gonna, using the information from the front of our queue, we're gonna visit its surrounding neighbors. So we're gonna visit this neighbor, this neighbor, this neighbor, and so on and so forth using the row and column that we popped out of our queue. And then every time we visit something, we're gonna push those values onto the queue. So then in this case, we'll push like row zero one now on the right. And then like the steps would increment by one. And then the K, since there's no obstacle on the right, it'll just still be K, right? And then we'll also push like the other value. So that was, so this part was one on the right. Then one on the bottom here, this part will be like row one, one, right? It'll be row one, one, push this. And then the steps would be increment by one and then our K would be decreased by one, right? K minus one because we're decreasing the step. There's an obstacle here. And then we'll also push like this neighbor, left one. So that's row one, zero, one, zero. The steps increased by one, right? One, it's still, yeah, it's still one. And then K is also K minus one because this is an obstacle here and we would have to remove our K if we go to this path. So yeah, and then we'll just keep running this and keep popping it and then visit this surrounding neighbor, this surrounding neighbor, this neighbor, so on and so forth. And then sooner or later, we'll just return like the minimum steps, okay? So that's that part. So yeah, that's what this Q represents and we push zero, zero. The current number of steps, zero and then K, right? So yeah, then we have this while loop, which is where our breadth-first search is gonna do. And while loop is while the Q is not empty, so that's what this is. While it's not empty, we're gonna keep visiting its surrounding neighbors, okay? For each of the parts. And we're gonna get the top value. So I call this auto top and Q dot front is gonna get like the first value of our Q. So it's kind of pops the first value of our Q. So in this case, I would like get the first, we get the first vector, right? The first array, take that and then we'll visit its surrounding neighbors. Then it gets the next one, pop it out, remove it, visit that surrounding neighbors and so on and so forth until we visit all the values inside our matrix. And then once we reach the end, we'll just return the minimum steps that it took, right? So here, yeah. So here, top is gonna equal to Q dot front, which is like the first array value in our Q. Okay, here what I have is X and Y and I just take it like from the top, from the current X and Y values that we have. And the reason why I do this is because top at zero is gonna represent X, right? And top at Y represents, top at one represents Y, right? Because we're pushing like the row and column, right? So remember, our array vector is gonna have is like four values, right? So right, the four values, which was row, column, row, column, steps, and then the number of K left, right? So yeah, it would be zero, one, two, three, right? So zero represents the row, one represents the columns, two represents the steps, and three represents the current K value. So here, X, which is like row, like current row, is gonna equal top at zero because, yeah, from the index from here that we're pushing, top at zero would be the X, which is like the row. And then column would be top at one, which is like Y. I said X, this should really be row and column, but yeah, you know what? X and Y is about the same thing as row and column. Yeah, so yeah, X equal top at zero, Y is gonna equal top at one, and that's because of this, zero, one, Y column one. Okay, and then I just pop it, Q dot pop, so that removes the front value. And C plus plus, the pop doesn't actually return anything. You have to call front and then pop for some reason. It is what it is. It's just the language. Okay, so this part is a little tricky. I'm just checking if our current row and columns are within our bounds of our grid, because it is possible that we don't, that we get out of bounds of our grid. So yeah, if the row is less than zero, or the column is less than zero, or the row is greater than equal to the grid's length, or the column is greater than equal to the grid's width, we'll just continue, right? We don't go to it, right? Because there's a chance that when we visit our neighbors, we somehow get out of bounds, and this would stop it from happening, because if this does occur, we continue, and we just go to the next value to remove next location to visit when we pop out of our queue, right? So there's really no, this way we'll prevent it from just going out of bounds, to going out of your board, right? This is just a condition. All right, here is a little trickier, but it's not that hard to understand. If X is equal to the size minus one, and Y is equal to grid size minus one, this is representing if our row is reaching the bottom right corner, and the column is also reaching the bottom right corner. So if we look at our board here, the bottom right corner is at this part, right? This is the bottom right corner. And if we look at the size of our board, the length here would be one, two, three, four, five, right, five, and the width would be three, right? So if our current row is reaching the length of five minus one, which is like four, five minus one is four, right? That would be the bottom right corner, right? The bottom right corner, because index from zero, zero, one, two, three, four, and our length is five. So if we reach four of our length, five minus one, which is four, that means we are at the bottom right corner for the row. And if our column, which is length three, right? The width is our three, right? And if our column is equal to three minus one, which is two, right? Two is the last index of our column, right? It's because it's indexing from zero, zero, one, two. That's also, that's the bottom right corner also. So if we reach the bottom right corner, we just return the steps, right? We just return the steps because that will be the minimum steps, right? So if we look at our queue here again, we're pushing a vector array of length zero of length four representing zero representing row, one representing column, two representing the steps and three representing our current K. So yeah, if we reach the bottom right corner, we're just gonna return the steps, the current steps, which is gonna be at position zero, one, two, right? It's gonna be at position zero, one, two. So that's what this is to return zero, one, two. Okay, yeah, okay. Now this part is a little trickier. Yeah, this part is a little tricky, but bear with me. I think you'll understand what I'm doing. I'm gonna drink some water. Okay, so remember our grid has obstacles and obstacles represents one if there's an obstacle and zero if there's no obstacle, right? So if we look at our grid, the matrix they give us, here zero represents empty, one represents an obstacle. So if we wanna check if there's an obstacle, remember, we just have to check if it's equal to one, okay? Now, yeah, so if our current grid at the current row and column is equal to one, that means there's an obstacle, right? Because it's either zero or one, one is an obstacle, zero is empty, right? Based on the grid that from the question they gave us. So yeah, now what I'm gonna do is that if there's an obstacle, what choice do I have? I could either remove it or I do nothing, right? I do nothing, go to the next cell, right? So in this case, in what situation would I have to do something, right? Well, it's simple, when I still have the K left, right? So remember, we all can eliminate at most K obstacles, right? So if my K is still greater than zero, I could subtract one from the current K. And so what was the state that we pushed? Remember, if we go back to our state, we have each of the, each time we push something onto the Q, right, it represents, we're pushing array representing zero representing the row, one representing the column, two representing the steps and three representing K are like our current K left, right? So if we look at this here, if our K is greater than, if our current K that we pushed from the top of our Q is greater than zero, I could subtract one, right? Because I have to subtract it, I could go to that location and subtract one. So that's what this is doing, right? If it's greater than zero, go to that location and subtract one. Otherwise, I'm actually just gonna continue to the next cell and just ignore everything because I can't go to that cell location. So I would have to just continue and not go to there. So like if we were going back to our example here of, if we go back to our example here, right? Let's say our K was equal to like zero and then I can't visit this obstacle and I can't visit that obstacle because I can't break it, right? I can't break these two walls. So in that case, I can't visit their neighbors either, right? So what I only can do is just ignore them, ignore them. So that's why we have a continue statement here. This part is continue and it goes on to the next whatever cell that is available from our Q. Okay, this part is a little more trickier, but it is what is. This is just checking if our visited is not equal to negative one. So this means that if we already visited the location, okay, so currently in our code we haven't really marked locations that the row and column that we visited yet, but if we already visited the spot and the current K value that we marked is greater than or equal to the K value, right? Zero, one, two, three, we'll just continue. Okay, we continue, we'll go to the next one. The reason why we check this is that what we're doing right now is we're actually gonna every time we visit something in the cell, we're actually gonna mark it with the current K that we have left with K obstacles. It's just easier this way and it'll let us check if we have any more K left that we could go to. So yeah, so basically what I'm saying is that let's say we wanna visit these three locations, the surrounding locations here, like these three, right? Here, I'm gonna just redo everything real quick. Here, I'll just redo everything real quick. This won't take that long. So yeah, what I mean is that when we visit a certain location, so we're gonna have like a separate board here. We're just gonna have a separate board here. Bear with me on this board. Eh, this here, here, here, right? One, two, three, four, one, two, three. Okay, so we're starting at zero, zero, right? We're starting at zero, zero here. And let's say I wanna visit the surrounding locations of this one, this one, this one, okay? So basically what we're gonna do is that we have the separate visited matrix grid representing if we already visited or not. So currently it's gonna get set all to negative one, meaning it's not visited. So all these values would be negative one, okay? And every time we visit a cell here, so let's say, well, first of all, the start part we're gonna visit, so we'll just mark this as zero. But anytime we visit a surrounding cell, so let's visit this one, right? At row zero one, we're gonna mark it with the current K that left that we have. So if we have like, let's say our K is equal to, I don't know, one, right? Well, then we'll mark this as one. That means in this current location that we've set this as, this is the K amount of obstacles we have left and we'll just mark it here, okay? And let's say I wanna visit the one on bottom right here for this cell. If I do visit this cell, right, I have to decrease K by one because there's an obstacle here, right? So then for that, I'll set this K to be zero, okay? And then for this one, it's the same thing. The one below it, we'll just set this to be zero because there's an obstacle there. So yeah, now what our condition is checking is that if we already visit this location twice already, meaning it's not equal to negative one, we have to make sure that the K is still, the current K that we have is still available, right? If I don't have any more K left, compared to whatever I've had previously here, I can't revisit this cell again. That's what it's saying. But yeah, so if visited at the current row and column is not equal to negative one and the current K, the current of like visited state that it was at previously is greater than equal to the current K that we have left, that means we can't go back to it, right? Because since we're decreasing K every time, so I'll just continue, okay? We just continue, go to the next one, right? Cause like if our K is equal to like zero now, right? I can't go back to the cell above, right? Because I don't have any more K left. I can't remove another obstacle again. So that's why, that's what this is, right? So yeah, visited at row and column is greater than equal to the current K, all right? Then we continue. Otherwise, let's just set the visited at the row and column to equal to our current K value or that we have left. And then yeah, that's what we do. And then here, what we're gonna do is we're gonna push all the neighbors. So we're gonna push the cell to the right of us. No, no, the cell below us at X plus one, row plus one and column. And then we're gonna increment the number of steps for it. So that's just top at two plus one because of the array that we're pushing, right? So we remember every time we're pushing an array of four values, the row, the column, the steps and then our current K. And this is an index at zero, zero, one, two, three. So yeah, at top at two, right? The current value top at two would be our steps. So we increment steps plus two, if that makes sense here. So yeah, we do top at two, which steps plus one, plus one. So yeah, every time we go to a new new step, we're gonna increase by one. So yeah, so yeah, and yeah. And then we do the same thing for all these. And then our current K, which is top at three, right? Top at three, so zero, one, two, three. That's our current K value that we're pushing. And yeah, we'll push that also. And here is just like the surrounding neighbors. So it's row plus one would be the one below us. Same column, y plus one would be the one to the right of us, right? The column to the right of us. Here is x minus one would be the one to the left of us. And y minus one would be the one up above us, I think. Wait, yeah. Yeah, x minus one is the one above us. y minus one would be the one to the left of us, okay? Left of us, yeah. So yeah, x, y is row and column. So we push those, and yeah. And then this would continue the breadth first search until it goes on and so forth until we reach all the values. And then, yeah. Now in the end, if we never returned anything, if we never reached the bottom right corner, from this statement above, we just returned negative one. Because that means we'd never visited it. And they said, if we can't reach it, just return negative one. So that's what it does. So yeah, I hope you guys enjoy this long video of trying to explain how this problem works. I think the hardest to understand is this part where if the cell that we're revisited at the current row and column is greater than equal to the current k that we have left, then you can't go there. So we just continue it. But yeah, I'm pretty sure this is pretty straightforward to understand. But yeah, I hope you guys enjoy this video. Once it goes through all the values, we'll reach like m minus one. We'll reach the bottom right corner from this code when it's done reach right. Hope you guys enjoyed this video. Like, comment, subscribe. I'll check you guys later. Peace.