Python Interview with an Amazon engineer

Watch someone solve the longest substring with maximum k distinct characters problem in an interview with an Amazon engineer and see the feedback their interviewer left them. Explore this problem and others in our library of interview replays.

Interview Summary

Problem type

Longest Substring With Maximum K Distinct Characters

Interview question

Given a string, find the length of the longest substring in it with no more than K distinct characters.

Interview Feedback

Feedback about Sagacious Astrolabe (the interviewee)

Advance this person to the next round?
Thumbs upYes
How were their technical skills?
How was their problem solving ability?
What about their communication ability?
Having a mechanism for following a strict problem-solving process will bring clarity to your problem solving and catch bugs before you write code. Craft 5-6 STAR stories, but don't expect that you would use all of them in an interview. Crafting on the fly will help a lot. If there wasn't a clear 'Result' from the story, like cost savings, performance boost, talk about what the biggest lesson learned was Good luck!

Feedback about Imperative Broccoli (the interviewer)

Would you want to work with this person?
Thumbs upYes
How excited would you be to work with them?
How good were the questions?
How helpful was your interviewer in guiding you to the solution(s)?
The interviewer gave me really good feedback: * Stick to a format for answering a technical question * Have 5-6 STAR stories for behavioral * Try and figure out what a behavioral question is asking for * Be patient with yourself, if the question is different than expected.

Interview Transcript

Sagacious Astrolabe: Hello.
Imperative Broccoli: Hi there. Can you hear me?
Sagacious Astrolabe: Yeah I can you hear you. Can you hear me?
Imperative Broccoli: Yes.
Sagacious Astrolabe: Awesome. Awesome.
Imperative Broccoli: Hi there, welcome. So this is kind of how I like to do the format. So I, almost said introduce myself, I talk a little bit about myself. And you can talk a little bit about yourself what you're hoping to gain out of this mock interview, if there's a specific item you're trying to focus on, as it relates to technical interviews, maybe I can steer the question or feedback index on on that what you're trying to focus on.
Sagacious Astrolabe: Okay.
Imperative Broccoli: And then we'll do a question. And then after that, depending on time, if you would like, I can do a behavioural question or two, there's a decent amount of big tech companies that add one or two behaviour questions in a technical interview. So yeah, okay.
Sagacious Astrolabe: Okay, cool. Cool. Um, yeah, I guess I'll tell you a little bit about myself. So yeah, my name is [Name]. I guess I go by Sagacious Astrolabe on interviewing IO. But I've been doing software, I guess, going on 16 years now. Mostly, though, one, language and framework Ruby on Rails, I'm interviewing at Bloomberg. But that's gonna be another Ruby on Rails position, or LinkedIn, which could be machine learning position. I don't know, though. So I feel pretty confident I can do Okay, on the Bloomberg one, mostly because it's for another Ruby on Rails team. So the there, there wasn't that bad, why did the phone screen, but I am worried about the LinkedIn interview, I feel like that one's gonna be a bit more challenging for me. So that's going to be the area I want to focus on is questions from the leetcode section for LinkedIn, I guess you can browse it by company or whatever. They did say tell me when the briefing that it will be easier medium for the phone screen and medium or hard for the on site. So that's kind of where I'm at. Another thing is to I'm like, really, really bad. I get super nervous. And I get, I don't like explain the problem. I don't explain what I'm thinking, at a slow enough pace, or quick enough pace to, to actually start to, to go through the interview efficiently. So I like I want maybe have like five minutes of here's what I'm thinking. And then another, whatever it be 10 to 20, maybe 30 minutes of of implementing the solution, actually, maybe between describing and implementing, we'll have a small discussion about if the approaches are right. And then I guess, as I'm implementing things, there might be more questions that come up. But yeah, a big thing for me is I'm not as structured as I want to be when it comes to the interview. And also just being mindful of time. So that's, that's the key areas that I'm trying to work on. So that's, that's, that's my side.
Imperative Broccoli: Okay, cool. So I'll tell you a little bit about myself. I am supposed to go by imperative broccoli. I am an engineer at AWS.
Sagacious Astrolabe: Okay, cool.
Imperative Broccoli: About a year and a half now. And during my prep, interviewing IO is actually critical. I did the 100 days of code. Okay. And then I would do a mock interview here, at least twice a week, if not once a week to kind of gauge my progress and so
Sagacious Astrolabe: Right on
Imperative Broccoli: Yeah. Just want to now that. You know, in big tech, I kind of want to give back. And then now that I'm conducting interviews, I want to kind of make sure I hone that. Muscle of conducting interviews.
Sagacious Astrolabe: Right on.
Imperative Broccoli: Yeah, so. So from what I've heard, I think we'll do a technical question. We'll do feedback. And then I actually looked up LinkedIn core values. And I can ask one or two behaviour questions that I have to make sure that I index on their core values.
Sagacious Astrolabe: Okay, okay. That works.
Imperative Broccoli: All right. Well, if you're ready, we can get started.
Sagacious Astrolabe: Sounds good.
Imperative Broccoli: Cool deal. So your language of choice I would assume would be Ruby.
Sagacious Astrolabe: Actually, though I do Python. When it comes to algorithms, I just find that leetcode favours C++, Java and Python. And I figured Python and Ruby are similar enough. Whereas most the time it transfers over. Although Ruby doesn't have, for example, a heap data structure built in, or I think there is a built in queue, but in any case, not as useful. That's actually what I ended up doing in my Bloomberg screen. It was giving a Python algorithm after I got into the Ruby and JavaScript stuff so cool. So yeah, this is where I'm comfortable.
Imperative Broccoli: Let's do that. And helpful. Remind me in Python so the block comments, I don't want to have to do
Sagacious Astrolabe: Do three quotation marks, and then
Imperative Broccoli: That's right. Oh, yeah. Okay. So, given a string, find the length of the longest substring in it, with no more than k distinct characters. So okay, to to input the string, and k being the amount of distinct characters. So in this case, it's for araa, and because c is right here, we noticed that that's more than two. So that's being four.
Sagacious Astrolabe: Yeah, okay. Okay, um, all right. So I guess, right off the top of my head, I'm thinking of using the two pointer pattern to solve this problem. So I'll just I'll just type the since that way, I don't forget this stuff. So yeah, two pointer. Left to right. Sometimes you can go right to left with it. But I think this should work, I guess. In this case, it's, wait, no, I'm sorry. I said wto pointer, but actually, it's more sliding window. I think that's actually the proper term, sliding window, because basically, the sliding window will is the substring of choice as we go through. So yeah, there is a left and right arm of this sliding window. But they act differently versus we're in to two pointer, they both move independently. Whereas in this in my version, I guess, in sliding window, you'll have one pointer moving, continue like step by step to the right, and then you'll have a left pointer that will get updated every so often. So really, the update of the left pointer is actually kind of what makes the big distinction between different versions of sliding window. So we update the left pointer, based on how many characters I guess Yeah, so. So this is actually the interesting part, right? Because how do you do the right condition to know when to update? Well, I'm looking at here. And I'm thinking that as we're doing the sliding window, we can keep a frequency count of characters that we've seen. Just to kind of kind of confirm, I know, this might be a little redundant, but we are using only lowercase or all lowercase English alphabet, right?
Imperative Broccoli: That's correct. Expect the input just to be lowercase?
Sagacious Astrolabe: Okay, because they're not not that it would it would have enough, you know, a constant factor to the algorithm, I guess, sliding windows, typically, all of them. So that's, this, this clarifies my algorithm will will be roughly O of N. But yeah, so the idea is, we keep a I guess you could do a HashMap, where we are always going to increment based on the next character, and occasionally we'll have to decrement when we get to this situation, I guess what it says was it no one more than k distinct characters? So actually, Wait, do I know I was thinking a frequency map but with K distinct characters is going to be a way how would we do this? Because you want to be able to know not just how many different characters you have actually know this might work because even with a frequency map, yeah, the frequency map will work. But we will have to delete the keys as we hit zero. Otherwise, we'll have extra keys and then we can keep we can find the number of distinct characters as the size of the keys and the hash a HashMap. So just to type out what I was thinking, so, as I'm coding, I won't forget things. Create a hash map to serve as a frequency map. And then so with each sliding window, there's like a correction phase. So basically, we're always going to be checking the size of, I guess, frequency map. Keys, I guess. And Python, this is actually just len. So checking that and making sure it's not um, is greater than i'm sorry, less than or equal to k. Because we want we can have at most k distinct characters and our sliding window. So yeah, checking checking this, if we do hit that that word is equal to k, or actually, if it's a being k plus one, then we have to when I guess, equal k plus one, then in that case, then I don't know what I'm doing with these arrows, and we just simplifies a little bit more. When that end is happening. Then we'll update left until this is equal to K. Right? So this update to left will, the basically and each time we update left will decrement. The counter. So I guess from the frequency map. Yeah. And then yeah, one final check. If frequency map of, of a character equals zero, delete from is of frequency map this so that way we make sure that this dot keys always gives us exactly the number of distinct characters in the current substring. Yeah, and basically, so the correction happens after but usually, there's like, the, the initial step is always to kind of I guess, I'll pay this frequency map for a given character. Something like that. Actually, this should be uhh right. Well, I guess if so I actually started doing some code. What what do you think of what I have so far? I feel like I'm going too much into the details with some of these lines. But what do you think of what I have so far? Is you have any comments or do you think i'm ready to like, maybe start coding this or?
Imperative Broccoli: So everything you've said has made sense so far.
Sagacious Astrolabe: Yeah.
Imperative Broccoli: If you if you could kind of recap. Your approach your design? Yeah.
Sagacious Astrolabe: So the the idea is we're going to have a for loop. Right is going to be the index that we're we're at at that at that point. And he's given point will we'll be updating this frequency map for the given character I guess it should be? Maybe string of right to be completely correct, because that's the character that we're looking at. But then the next step would be, I guess, this is more like an initialization step. Empty. Right. And then, so we're going to update this, this, this mapping, check the size of the keys of the mapping, make sure that it's below, equal to or below K. At any point, if we hit k plus one, then we know we need to have to perform the correction, I guess they would correction could be more like here. But yeah, the correction happens basically when we hit the k plus one size, and then we'll start up bidding left. And basically incrementing just say increment left until and then basically in each increment of left, we're going to do I guess, frequency map, string left, minus equal one. And then or decrement from the map, or we'll delete the character we'll delete the key entirely. If we hit the frequency map is equal to I can even do this now. It's even more succinct. And yeah, I mean, it that's kind of the beauty of Python, in my opinion is always you could get so close to pseudocode that particularly is this. It is code. So so yeah. So I guess that I helped the We the correction is we kind of increment left until we hit this is the key is equal to k as we I guess we decrement. Let me see if I had this ordered correctly. We don't need to do that until I when this happens. So yeah, so we go into this and then yeah, we start decrementing. Okay. Yeah, I confused myself for a second there. Does that make sense so far?
Imperative Broccoli: Yep. I think that makes sense. Okay, cool. Cool.
Sagacious Astrolabe: So if everything looks good, want to try to implement this? So I guess, longest name and longest substring K distinctsa. A little long, but it is exactly the problem we want to solve. Yeah, we're given a string. We're going to create a frequency map. Yeah actually, default? dict? Actually, no, and I'll just, I'll just make an empty one. So yeah, so we're gonna go for each. I'll initialise left as well. For right in range of a length of string. I'm going to do frequency map. Actually, if the key in this case is, right, and frequency map, actually, if it's not in here, then we can initialise it to zero. Okay, otherwise, or I guess in all cases, we want to increase it by one. And then we check the length. Yeah. To when this is equal to k plus one. And we're going to start decrementing. I'm sorry not decrementing we're not gunna start shortening our string, which is act of increasing length. But actually want to make sure we do this line first, before we do the increment. And then checking if it's, if it's zero at that spot. And then i think it's delete, I think D E L is a keyword. Frequency map. String left. So this should give us Yeah, in Python, you have to, if you want to give a string with a certain length, I guess, in this case, it would be string left, right. Plus one. Yeah. Because in the case of if it's just one, if the length of our substring equals one, then we would have zero left would be zero, right would be zero. Yeah, string if string exactly. I guess I'm just trying to check a boundary case here. Just to make sure that I haven't made a goof. And my algorithm is that when string is equal to like, say, a, and we had basically would give the exact string as a result. So what will happens, I'm just, if everything is is cool, so far, I'm actually gonna do a little dry run with my code if that's okay.
Imperative Broccoli: Yep.
Sagacious Astrolabe: Okay, cool. Cool. So yeah, so I guess, in that case, right, is basically only ever going to be zero. That's the way I guess the range will always be have a zero up to n minus one. So it's just zero. So then string of zero not in frequency map, this is true. So we add a to the frequency map equal to zero and then down here becomes one length of keys. I guess that I just I just now realised that what if what happens when k is greater than or equal to the length of the string? Actually, that's one one special case we have to keep track of. So we are going to be given K. or We're going to say if the length of string is less than, or is greater than or equal to k, this return string itself. But we're going to kind of ignore that for this. This case, I just want to see what happens actually, there's another question just realise it doesn't doesn't make sense for K to ever be zero. Or what would happen if it was or negative for that, for that matter. Um, is that something that we should really would be in scope for this? Or can we just say like, this is probably the most extreme it'll get in terms of, you know, pathological cases.
Imperative Broccoli: I think for here, we could assume that k will always be a number greater than zero but less than the length of the string.
Sagacious Astrolabe: Okay, okay, so then this check is redundant. So that's cool. That makes it a little simpler. Okay, so, yeah, the next step would be, as I'm running this, the number of keys is one. Actually, yeah, so in that case, k would would always be at least one. So what one plus one is two, this is not true, since one is not equal two. So then I would go to the next element in my list, which is none, there isn't any, it's just the empty array, or actually ranges, just it's just this thing. That's empty is one element array. So then we can go straight to the end. Yeah. So then left, column, right plus one, it should be 01. So then it should get back to string a. Okay, so that is actually the one main case that one's edge case. But I guess, should we do another dry run for the given example, on line 25, and 26?
Imperative Broccoli: Sure.
Sagacious Astrolabe: Okay, okay, cool. So, string is equal to this thing, k is equal to two. So then, the length of this is six. So then range is going to be from zero up to five, basically, starts at zero. The character at this point is a. It's not in the frequency map, we set it to 0, one there. The number of keys is equal to one. But then we have k is equal to two here, two plus one does not, yeah one does not equal to three. So we can skip this and go to the next case, where right is equal to one. That's the R. And then it's not in the frequency map. So I want to have maybe I'll just make a little bit more space to keep track of what's in my frequency map. I want to do this maybe something like this a equal to one now. R is equal to zero, and then when it gets down to here, it'll be equal to one. There's now two keys in here. Two plus one does not equal to three. So we skipped the next one, we now we have the a the second a, when right is equal to two, it isn't a frequency map. So it could just update here, we only still only have two keys. So it's this is still false. We do it again for right equals three. A is equal to three now. I think the interesting case is actually the next one, which is the C right is equal to four string of right is C not in a frequency map. C is now equal to zero, I guess that's to be consistent and not confuse yourselves. We'll copy those. But then yeah, the next step is to increment that we now have three keys. And it does, you have the number of keys does equal to none, it does equal k plus one. So we've gone over, so we will delete from the frequency map. I'm just gonna remove this one. And I'm just gonna say the left is still zero. So I'm just going to notate up here left is equal to zero. And we're decrementing the thing as zero which is the A, so we're going to remove the A or remove one of them. And increment left by one less is equal to one is a, the frequency of a equal to zero? That's not true. It's just still just two. So we can go on to the next one. The next one will be the R actually wait I'm thinking now that left and right will definitely change over time that I should be keeping track of the right. Yeah, I definitely was not keeping track of the best stuff in the best right we found at any given time. Find the longest substring so then Yeah, so there's gonna be another phase in here that I didn't think of in my initial solution of checking the length of the substring. So check length here. So, let me see, let me see, let me see how I want to do this. Maybe I'll call it start zero and then blanks. There's also zero and I say, if right minus left is greater than or equal to length, actually just was greater than length, which starts at zero, then less is equal to start. And then right is equal to left. No i'm sorry, start is equal to left. And length is equal to right minus left. Okay. Now, this is probably the better way to keep track. Yes, start. Start plus length. Okay. Okay. So I definitely wasn't keeping track of that before. But now, I gotta catch up a little bit here. Yeah, I'm gonna have to rewind a bit. Because let's length is equal to zero. That's that. Basically, I have to capture the result when length is equal to zero. I'm sorry, left is equal to zero. So what are we doing here? So length starts out as zero, I guess, as this had been expanding, right was at a four right? So then this is going to be right minus left is equal to four, length is equal to whatever it was, but now, after this line, length will be equal to four, start is equal to zero. Okay. All right. Here's another correction. I don't know how I skipped that. In any case, so yeah, so we were decrementing this frequency map, we already decremented the first A, from the frequency map, we need to decrement continue decrementing until we no longer have the number of keys equal to three. So anyways, we're we're here uh length, left is equal to one. It's still not zero yet. So we at the no i'm sorry, we're at the r. Yeah left is equal to one, then that's, we're moving the R so then we do. Yeah, we do delete R here. So then it goes away altogether. Via this line, so then, the next step is left is equal to one. Okay. What's the key how many keys does it have now, and should have just two. So it's two equal to three. That's not the case anymore. So actually, we can loop back around to I think, right? Yeah, right. Left is equal to one now, because it's at the R. And then yeah, we're at the R and the C. But I still have no I'm sorry. If left is equal to one, then wait a second. No, I'm confusing myself again, this let, this increment needs to happen after this. That's where I confuse myself. Because if your decrement thing, then immediately after, as soon as you hit zero, you should delete it. And then you can increment. So that was another small bug that I found. So that would be the next step would be to left is equal to two. So now that makes sense. So now you're at the A C. So now right is equal to five. That would be 012345. Yeah, the i. So is is not in there is equal to one. And then again, we would hit wait. So what was this again? Five minus two with length equal to four, this is three, three is not greater than four. So we don't set length start at length. So then yeah, we would continue on, I guess now these are equal. Or the left is equal to two. So we decrement to a again, so now is equal to one. We go to three, a is equals is going to be the, a third a, would decrement the one or the A once more time and then now A is equal to zero. So delete it immediately. And now we're down back down to two. And then we can loop back around to right, right is on this, the last number was five. So the now we can get out of the loop, and now we have start is equal to zero, length is equal to four. So this should actually be the first four characters of the string. So some some fumbles here and there. Definitely, I missed the updating the length, I'm updating the start and length, or I didn't even have them when I started. And then also, I didn't catch that I need to actually check immediately after decrement thing that is equal to zero and delete when we find that and then, and only then do we do the iteration on left. I confuse myself there. But yeah, I think that's like I said, it's time it's the space complexity is in the the time I'm sorry, the time complexity is N the space complexity is actually if this if we have a fixed set of characters where I guess C is the number of characters then this is going to be 26. So they basically the the space complexity is O of 26, or O of one for constant time. Yeah, characters and alphabet. So yeah, I think that's the trivial case. And then the main case, I got both of those. How are we doing on time?
Imperative Broccoli: We're doing good. We have a few minutes.
Sagacious Astrolabe: Okay.
Imperative Broccoli: Should we should we call this function? Some test cases?
Sagacious Astrolabe: Oh, yeah, definitely. If you if you're okay with running running the code. So let's do that. So let's go see if I actually get it correctly. I want to do it by hand. And this is this thing, K is equal to two. Oh, damn. How did this happen? Okay left is minus equal one. I'm just gunna look at this stuff at the top first. Because I thought I wouldn't hit this case just yet. But I guess just to do a quick print about which I'm probably off by one or something somewhere. It usually what happens when I see this kind of stuff? Zero Oh I'm sorry. How to get, Oh! I see. I see. This is yeah, this is the error. It should be right and then string right. Okay, so that was the thing that we were expecting. Here.
Imperative Broccoli: Is it?
Sagacious Astrolabe: I think so. Yeah. It's the line 22. Yeah. I guess actual and then expected like this. The equal sign and make it a little prettier. Maybe even two lines. I don't know, in any case. I don't want to spend too much time on making it pretty. we should probably put in some more test cases. So let me think what oh,
Imperative Broccoli: This. I just want to call out this is I don't believe this is the output we're expecting.
Sagacious Astrolabe: Wait a second are you sure it says output oh output four Oh, damn it. I don't know how I didn't catch that. Yeah. So I could I could just output length. It's an even simpler problem. Yeah. Thanks for catching that, by the way. I was I was thinking more about the substring. But yeah I guess it wasn't that much of a risk of actually get the substring instead of just the length of the substring. Yeah, this should be yeah four Okay. Cool. Cool.
Imperative Broccoli: I have if you want I have some more test cases.
Sagacious Astrolabe: Okay.
Imperative Broccoli: Add some fun here. I'll just add it here at the top and my little block here. Here we are.
Sagacious Astrolabe: All right
Imperative Broccoli: Don't want to touch your code or anything.
Sagacious Astrolabe: Yeah I hear you, I hear you I guess
Imperative Broccoli: Confines in my comments.
Sagacious Astrolabe: Yeah. I guess our test cases gonna be. Not what I want to do, not the square brackets. So this should be triple with the arguments maybe I'm spending too much time trying to make this general, I tend to do that sometimes. Let me let me just slow down and just do some copy, rough copy paste.
Imperative Broccoli: Perfect.
Sagacious Astrolabe: Yeah. K is equal to three. I guess we'll see what the output is. Five, I think was that expected? Yeah, it's gotta be the Yeah. CBB. Yeah okay, cool.
Imperative Broccoli: Cool, so we just have just a few minutes left. Now that we have a working implementation here, is there ways you can improve this or do anything different?
Sagacious Astrolabe: Um, I mean, yeah, I guess since we kind of figured out we don't we don't need the start, then that can be removed. Yeah, remove that. Then, I guess this never would happen. But we could we could maybe do just like if, if a number of keys is greater than than k, maybe that's a little bit more readable. Because it's basically alligns with no more distinct character more than no more than K distinct characters kind of specification. So maybe that is good for the next person to read like. This actually could be a one liner length is equal to min right minus left length? I'm sorry. No, it's not it's supposed to be max. Yeah. What else? Yeah, I was gonna use default dict, which is basically an ordinary hash map, except that when you try to get some, you when you ask for a key that's not there. And it defaults to whatever you provide it in this case, the default is a integer, which is a zero. So I could actually remove this line altogether. And just increment as needed. I could use there's another Python method called enumerate, that would get me both the character and the pointer at the same time as a tuple. But actually, I feel like forcing myself to write it out this way. Kept from getting like confusing, because really, there's just two spots in the string that we're trying to index, not just one. So forcing myself to do this syntax. Maybe some developers might not like the double brackets. And then in any case, we could always, you know, maybe make it a new variable or whatever. But I see that it's more cosmetic than anything. I mean, I guess just to reduce on some redundant lines, since it's just they both start at zero. Yeah, I mean, I don't know if there's anything else that jumps out at me as stuff that we can improve. I think that's kind of as tight as we can get it without it being really obscure read yeah.
Imperative Broccoli: Cool. Thank you. That concludes the technical portion. I do have have a behaviour question.
Sagacious Astrolabe: Okay.
Imperative Broccoli: And then afterwards, we can go into feedback.
Sagacious Astrolabe: All right.
Imperative Broccoli: Yeah, so let's shift gears here. So I took some time to kind of take a look at LinkedIn, its core values, and my question bank. So tell me about a time where you set an ambitious goal, either for you or your team and achieved it.
Sagacious Astrolabe: Actually, so I, I set, I set an ambitious goal of refactoring, part of the codebase that I currently work on at my current job. We build forms for colleges, not too long to explain, but to you is kind of like the tech department for those colleges that don't have their own and want to do online learning. So we handle everything from the marketing, to college applications, learning management systems, video chat, things of that nature. So one of the things is when we have a college application things that I that I build up my current job, they might choose different things from a drop down. And then we want to allow an administrator to decide if that question, another question should be hidden or shown based on a previous question, answer, or answer. And so basically, we came up with this thing, and a database called rule sets, which a rule is just a bind a Boolean expression of some sort, like comparing a value in and in the form to a fixed value in our database. And it could be like, a must equal b, or a does not equal b, or some other combination, like as part of a list. In any case, we had had a lot of problems in that area of the code, where all these foreign key relationships formed, formed a cycle in the database, so that, in other words, the there was a foreign key that went from rule to rule set, I'm sorry, from rule set to rule and then back up the rule set. And that was allowed us to have parent child relationships. But it also made it really, really hard to query. So one thing I actually came up with was to replace the that way of doing it was, instead of a cycle in the, in the foreign primary and foreign key relationship, I came up with, instead of having it just go one direction, where it would go from, basically, I came up with an idea of a filter, as a replacement for a rule or rule set. And a filter expression is a Boolean expression represented as an abstract, abstract syntax tree. So you have as the root node, the operation, and or, you know, or equality, not equality. And then the leaves of that tree are the values are either a concrete or a rather a static value that's stored in the database, or dynamic value as for whatever question we want to look up at that time. So basically, I had to, like replace this whole entire thing. And then actually, I didn't get to finish all of it. There was another phase. Basically, after that refactor, I think that was about six or seven months later, they've come to a realisation that rule sets maybe isn't the best implementation for these kinds of functionality. So going forward, where they're, they're probably gonna start deprecating the rule sets in favoure of my filter thing. But But I guess that's kind of the long and short. It well, I think one of the big pieces to it was, was getting buy in from my fellow engineers. But it was kind of weird, because what had happened was, I'd always I'd presented all of these diagrams about how I was going to do it. And I basically showed some snippets of code about how I was going to do it. But I need to my sense, my engineers, my fellow teammates, actually, we're never, had never heard of an abstract syntax tree. And that actually, basically became a learning thing where I kind of taught a short thing to some of the other engineers what, what exactly abstract syntax tree is, not that it's the most optimal, but it is a way of storing arbitrary expressions as data in the code and therefore allowing administrators to create arbitrary expressions as needed. I would love to keep doing more and more that kind of work in my code base but but yeah, that was how the long the short of that experience so I don't know if that answered all your questions, or if it was more questions you had as a follow up or
Imperative Broccoli: Um, I do have follow ups. But I want to make sure we get the feedback in. So I want to get through that. And then we can talk about some of the feedback on this question of what I've written down thus far. So cool. Well, yeah, let's, let's move, move on to feedback. So first of all, good job, you got the definitely solve the problem. You caught yourself a few times, which is good. The big thing that I think is a good opportunity to improve upon is to add more to this paradigm that you have here of writing down your approach and your thinking, which a lot of folks don't even do that. So I applaud you for, for starting. So one thing that I've I've seen done, I think may assist you is, as a way to kind of help follow a step by step guide. I've seen a lot of folks essentially create almost like a think of it as like a notebook, I don't want to say Jupyter Notebook, but almost like a notebook of steps for the problem solving process. And then you come in and fill in the blank. So here I would put, input questions, you know, and then well, so let me just put in your headings. So if you get a chance, if you're able to, started adding headings here that were present the various steps. Right. So here, then it reminds you, oh, wait, all is this all lowercase? Right? And so it kind of gets you thinking of how do you fill out this heading with detail, almost like if you have an outline for a document, and you want to fill out detail, this helps remind you of asking those questions all over again. You know, a is null. Right. And so you go through all of the things you think are needed to solve this head. Right. And then you initially set approaches, you got sliding window, right out of the gate, which was cool. So, you know, then you could say, not, let's say you didn't want to do a naive one. You could you could say double loop, right? And then the next one, you'd be like, well, optimal, I think is do you see where i'm going with this. So it's essentially just kind of like you're filling out a document once you start with these high level things that kind of help steer you. Right, right. Right, and then, which I think will be super helpful. And then when you do the walkthrough, then you could say, Okay, for a second. Okay, well, for this approach, you know in this, you use your own kind of way that is most helpful to you. But like, you could essentially say, okay, cool. So my, my left pointer or my left in this window, Left Bound is on a, and my right one is currently on r right, however you want to illustrate this, right, right. Okay, now I want to move now I want to move on. Right? And then as you're kind of talking through how you want to approach it, it's clear you have this entire document, so to speak, because every interviewer, yes they're going to take their own notes. As the interview is going on, like their interviewers, at least some big tech, write a whole book, as you're talking about everything you did, but they don't, wont to always remember. And so they'll have to come back. And if you already have this entire thing laid out, it's super easy for you to keep to steer you and like goalposts so to speak, and also they can refer back super easily.
Sagacious Astrolabe: Okay, okay, cool. Yeah. All right. Yeah, I actually I was trying to make something like this before and I had different advice about how to structure it, but I think yours actually ended up being the best so far. So thank you for this. I actually did take notes on exactly those bullet points you, you laid out here, so thank you.
Imperative Broccoli: Yeah, so in the interviews I've done, actually learn that from, from someone on here essentially just like before you even begins, if you have time, just lay out all the headings in your problem solving process. And then it helps in the heat of the moment and the nerves and all of that. You just see it right in front of you like, Oh, I missed. I miss covering all my assumptions, because it's blank here.
Sagacious Astrolabe: I would, I would wonder what an interviewer would think if I like had copy and pasted this directly to the thing where they'd be like, oh, man, are they cheating somehow?
Imperative Broccoli: Right? Yeah. I don't know about copying, but
Sagacious Astrolabe: Just memorising? I've memorised a lot of algorithms already, just so that we can get good when they need it when they're needed. Like, you know, some of the more complex ones like Union find, or topological sort, like I just know how to do, like off top my head. I just no problem. I could do this one too. So just something to do then. Okay. Well, cool. This is actually a good, good advice. It's perfect. So let me take a step back. And you can continue.
Imperative Broccoli: Sure. And so just just to really quick add on that, I think you would have caught not capturing the maximum lengths here.
Sagacious Astrolabe: Right, right. Right.
Imperative Broccoli: I saw it. And I was basically letting you go. To essentially have this conversation with you. And just, I knew you would catch, you would catch it as soon as you would run it, which and you did and you you needed very little hand holding, which is a major plus, you caught bugs yourself. So as a as like a to be how do I phrase this since every company is different? I think having even caught even if we shifted even further left, that would put you over, you know, like the top 5% percentile of applicants by far.
Sagacious Astrolabe: Yeah yeah yeah
Imperative Broccoli: But catching it yourself was good. Catching it before code is even better. Definitely. And so what mechanisms right, can you instil in your problem solving process, like this notebook, like set up to do that? Cool. And then the last thing I'll leave is just something fun, I do this kind of tongue in cheek, because it's not, I want to preface that this is not like a who can do better sort of thing. This is more of like, if you're considering using various Python features. I always add after spending, like, the fourth time of redoing this problem, I found an elegant way. And so I only just add this just as a, a cute little. What you
Sagacious Astrolabe: Okay, okay. Right, right
Imperative Broccoli: But I found this thing called Python, you can use the Python set function.
Sagacious Astrolabe: Ah, I see. I see. Yeah, but you pay the set construction costs each time each time. You could maybe even have a running set as well. But But then again, set is just implemented by a hash table. So you might as well have the values anyways. So that's that's kind of why I went with that. And instead of using a set, but yeah, that works, too.
Imperative Broccoli: Yep. Again, not not at all trying to say which one I'm just using. Just showing different different ways to solve the same problem. Can get your gears turning for the, for your next problem.
Sagacious Astrolabe: Right on, right on.
Imperative Broccoli: Yeah cool. Um, so yeah, so that's what I have for the technical. For the behavioural one, I'll phrase my feedback as a question. The answer you gave me about your your refactor of your, your filter, Boolean expression. Solution. Does that do you think that answered the question?
Sagacious Astrolabe: I don't actually I didn't prepare at all, for the behavioural at all. Like, there was. I was trying to come up with something that I had done recently. And I don't know if that's actually a really a good answer to be honest with you. I think that if I was to give more like I now that I think about it, I probably could have just talked about because so on the project I worked on we did she take a huge legacy Python web application and convert it to Ruby on Rails which took multiple years, is actually the main thing that I was hired on to do. And so if, if I was talking about like a huge project that, you know, maybe fits a better scenario, all the scenarios for a behavioural question, that would be better where whereas the refactor is like completely almost solo, because unfortunately, my colleagues don't know what, about abstract syntax trees. So it almost looks like I'm talking down to them in a way. Now that I thought about it. And, you know, it's unfortunate that that was what I came up with. But it was, again under pressure. And I just thought of something I just started talking about it. So. But yeah, I think I probably could have come up with something like, there was a like, I would say about like three to six month process where we were converting a lot of these college applications from the format that the Python version understood to the one that the Ruby on Rails version understood. And so that transition process was like, you know, every step of the way, we have to make sure that we didn't mess data transformations up, or that the reports are being sent out properly. All these other little steps that we have to make sure are lining up. And I actually had a hand and help, we hired out some contractors for that three to six month stint of work, where it helped out, we had some more like junior or intern level engineers to handling a lot of this legacy code that was not really going to change, and just needed a couple of edge cases checked on. So there would have been a lot more opportunities for different, like things within the process of changing that whole entire product over but yeah, I picked something that I knew right away, which was, again, out of nervousness, what happens is, if I don't recognise a problem right away, I'll default to these sometimes that scenarios, you know, I, or I'll forget this dimension things along the way. So, yeah, that's okay. Well, it wasn't the best answer. But so definitely, you know, what do you think about this the second answer I kind of gave without have been a better one to give do you think.
Imperative Broccoli: So here's, here's what I'll say. Yes, it was an improvement. Here's, here's what I'll say pro Tips on behavioural interviews. Yeah. The first one being, yes, you should probably prepare five or six. Really good stories, good narratives that follow the star format. Okay, situation task action result? I don't know if you're familiar with that.
Sagacious Astrolabe: I feel like I've heard it once before. But this is like, I think I never had it laid laid out to me. You said situation tasK action Result? Yes. Okay.
Imperative Broccoli: STAR. So, yes, that's definitely a great value add, if you have five or six of those stories ready to go. But what you'll end up finding is that I wouldn't try and over index so hard on those five. It's a great exercise. But what's going to end up happening is that you will get a question that you don't have a story for right?
Sagacious Astrolabe: Right.
Imperative Broccoli: So then then what do you do? So having gone through the exercise of crafting five or six of those, you can get a little bit better of crafting on the fly. And kind of my second big piece of pro tip is that once you have those narratives, then if you're asked something that you don't have a story for, you can do a few things, one, forgive yourself or give yourself time. There's a lot of times where you'll be asked something and you're you feel like you're in this rush, that if you don't answer immediately, you won't, you won't succeed. Be willing to give yourself time even even tell the interviewer, hey, I actually don't have one off the top of my head. Give me a moment. Take you know, 10 seconds. And because you've gone through those exercises, it'll be easier for you to craft in that format.
Sagacious Astrolabe: Okay, okay. Yeah.
Imperative Broccoli: And then the next little thing on that is you can also ask questions about the question to validate.
Sagacious Astrolabe: Oh, okay. Yeah, I don't do that enough.
Imperative Broccoli: So for instance, if I asked you tell me about a time where you set an ambitious goal and achieved it. Let's say you don't have a go to story for it. You can say, Hmm? Do you mean in a technical sense, or would you prefer like a team like product? Type of goal. Right? So not not only are they giving you more context, let's also just flat out giving you more time to think about.
Sagacious Astrolabe: Yeah, true, true, true.
Imperative Broccoli: So yeah, Oh yeah. Okay. And then the last piece of pro tip, actually probably shouldn't be first before be patient with yourself is, once you craft the stories, see if you can snuff out the meaning what signal they're trying to get after with that question? So for example, if I asked you tell me about a time where you failed to collaborate with a peer, right? What would you think I was trying to get at with that?
Sagacious Astrolabe: I guess call Yeah, when I failed to collaborate with a peer, I guess. You're trying to figure out if the candidate knows how to handle conflict or potential conflicts or potential disagreements. I mean agreements are a huge part of software as it set, standardised things? So basically, their ability to kind of like, work with possibly conflicting opinions in a team?
Imperative Broccoli: Yes, yeah. So that's definitely one, just figuring out how you go through conflict. I would also consider thinking about because the key words there where you failed. Anytime you hear the word you failed, or the words you failed, it's probably they're probably wanting you to be willing to admit that you failed. If, if you if your answer includes something about your peer either wasn't smart enough, or they did something wrong. You know, it's probably going to be it's great way to snuff out good or bad signal. But because the key word there is you failed, if you're not talking about yourself in your answer, that's great signal for them to not incline. So that's just kind of like an exercise to think through some of these questions.
Sagacious Astrolabe: Right, right. Okay. Okay.
Imperative Broccoli: So yeah, so that's kind of my tips to consider. Because you will never be able to pattern match all of the stories you've, you've prepared to all of the potential questions you could be asked.
Sagacious Astrolabe: Right, right, right. Definitely.
Imperative Broccoli: Yeah, so that's, uh, that's all I have.
Sagacious Astrolabe: Yeah, well, actually, that was that was really good actionable advice. Thank you so much. That was awesome.
Imperative Broccoli: Yeah, my pleasure. Like I said, you got the problem solving. In a good spot. You fix your own bugs. I think you're gonna do really well in an interview. So.
Sagacious Astrolabe: Okay, cool. Well, yes. Thank you so much for for all that you've done. I think we're a little over time. So
Imperative Broccoli: All good. No worries. And I'm gonna go ahead and just share my contact info. If you want. I'm happy to. If you have any more questions. Yeah, up to you know, no pressure.
Sagacious Astrolabe: Okay. I'll share mine as well. I think it's to the platform, right. You can click that. Yes, share my contact and then we can we can exchange emails or whatever. Okay, cool. Right on.
Imperative Broccoli: Awesome.
Sagacious Astrolabe: All right. Yeah. Thank you so much.
Imperative Broccoli: Yeah, absolutely. Good luck, and have a good one.
Sagacious Astrolabe: All right, you too.
Imperative Broccoli: Bye. Bye.
Sagacious Astrolabe: Bye.

We know exactly what to do and say to get the company, title, and salary you want.

Interview prep and job hunting are chaos and pain. We can help. Really.