Skip to content

nathankurt/Practice-Interview-Questions

Repository files navigation

Practice-Interview-Questions

Just a bunch of practice interview questions that i'll work on. te

Go To

Amazon Coding Interview Question - Recursive Staircase Problem

This question asks you to find the number of ways you can go up a staircase given the size of the staircase and knowing you can only take one or two steps at a time like so.

image

The next part of the problem asks you how you would do it if you were given a set of steps that you could take. So for example given the set X = {1,3,5} that means you can only take 1 step, 3 steps, or 5 steps at a time. And then you have to figure out the number of ways to solve this problem.

source

Return To Top

Google Coding Interview Question - First Recurring Character

This question asks you to find the first repeating character given a string of characters like so:

"ABCA" -> "A"
"HELLO" -> "L"
"COW" -> "NONE"
"DBCABA" -> "B"

image

source

Return To Top

Amazon Coding Interview Question - K Closest Points to the Origin

Given a list of tuples like points_tuple = [(-2,4), (0,-2), (-1,0), (2,5), (-2,-3), (3,2), (1,0)] find the k closest points to origin. So in this case, if k=2 then the k closest points would be (-1,0) and (0,-2)

image

image

source

Return To Top

Daily Coding Problems

(7/19/18) Problem 1

Given a list of numbers and a number k, return whether any two numbers from the list add up to k.

For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17.

Bonus: Can you do this in one pass?

Return To Top

Problem 1 Solution

This problem can be solved in several different ways.

  1. Brute force way would involve a nested iteration to check for every pair of numbers. This would take O(N^2).

  2. use a set to remember the numbers we've seen so far. Then for a given number, we can check if there is another number that, if added, would sum to k. This would be O(N) since lookups of sets are O(1) each.

  3. Yet another solution involves sorting the list. We can then iterate through the list and run a binary search on K - lst[i]. Since we run binary search on N elements, this would take O(N log N) with O(1) space.

Return To Top

(7/20/18) Problem 2

Given an array of integers, return a new array such that each element at index i of the new array is the product of all the numbers in the original array except the one at i.

For example, if our input was [1, 2, 3, 4, 5], the expected output would be [120, 60, 40, 30, 24]. If our input was [3, 2, 1], the expected output would be [2, 3, 6].

Follow-up: What if you can't use division?

Return To Top

Problem 2 Solution

This problem would be easy with division: an optimal solution could just find the product of all numbers in the array and then divide by each of the numbers.

Without division, another approach would be to first see that the ith element simply needs the product of numbers before i and the product of numbers after i. Then we could multiply those two numbers to get our desired product.

In order to find the product of numbers before i, we can generate a list of prefix products. Specifically, the ith element in the list would be a product of all numbers including i. Similarly, we would generate the list of suffix products.

This runs in O(N) time and space, since iterating over the input arrays takes O(N) time and creating the prefix and suffix arrays take up O(N) space.

Return To Top

(7/23/18) Problem 3

Given the root to a binary tree, implement serialize(root), which serializes the tree into a string, and deserialize(s), which deserializes the string back into the tree.

For example, given the following Node class

class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

The following test should pass:

node = Node('root', Node('left', Node('left.left')), Node('right'))
assert deserialize(serialize(node)).left.left.val == 'left.left'

Return To Top

Problem 3 Solution

There are many ways to serialize and deserialize a binary tree, so don't worry if your solution differs from this one. We will be only going through one possible solution.

We can approach this problem by first figuring out what we would like the serialized tree to look like. Ideally, it would contain the minimum information required to encode all the necessary information about the binary tree. One possible encoding might be to borrow S-expressions from Lisp. The tree Node(1, Node(2), Node(3)) would then look like '(1 (2 () ()) (3 () ()))', where the empty brackets denote nulls.

To minimize data over the hypothetical wire, we could go a step further and prune out some unnecessary brackets. We could also replace the 2-character () with #. We can then infer leaf nodes by their form val # # and thus get the structure of the tree that way. Then our tree would look like 1 2 # # 3 # #.

Return To Top

(7/23/18) Problem 4

Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.

For example, the input [3, 4, -1, 1] should give 2

The input [1, 2, 0] should give 3.

You can modify the input array in-place.

Return To Top

Problem 4 Solution

The solution is way more complicated but doesn't use any extra space

Our lives would be easier without the linear time constraint: we would just sort the array while filtering out negative numbers, and iterate over the sorted array and return the first number that doesn't match the index. However, sorting takes O(n log n), so we can't use that here.

Clearly we have to use some sort of trick here to get it running in linear time. Since the first missing positive number must be between 1 and len(array) (why?), we can ignore any negative numbers and numbers bigger than len(array). The basic idea is to use the indices of the array itself to reorder the elements to where they should be. We traverse the array and swap elements between 0 and the length of the array to their value's index. We stay at each index until we find that index's value and keep on swapping.

By the end of this process, all the first positive numbers should be grouped in order at the beginning of the array. We don't care about the others. This only takes O(N) time since we swap each element at most once.

Then we can iterate through the array and return the index of the first number that doesn't match, just like before.

Another way we can do this is by adding all the numbers to a set, and then use a counter initialized to 1 Then continuously increment the counter and check whether the value is in the set.

Return To Top

(7/24/18) Problem 5

cons(a, b) constructs a pair, and car(pair) and cdr(pair) returns the first and last element of that pair. For example, car(cons(3, 4)) returns 3, and cdr(cons(3, 4)) returns 4.

Given this implementation of cons:

def cons(a, b):
    def pair(f):
        return f(a, b)
    return pair

Implement car and cdr.

Return To Top

Problem 5 Solution

This is a really cool example of using closures to store data. We must look at the signature type of cons to retrieve its first and last elements. cons takes in a and b, and returns a new anonymous function, which itself takes in f, and calls f with a and b. So the input to car and cdr is that anonymous function, which is pair. To get a and b back, we must feed it yet another function, one that takes in two parameters and returns the first (if car) or last (if cdr) one.

so it ends up something like this:

def car_answer(pair):
    return pair(lambda a, b: a)

def cdr_answer(pair):
    return pair(lambda a, b: b)

or you can use the __closure__ method and call the first value in the cell

def car_my(pair):
    return pair.__closure__[0].cell_contents

def cdr_my(pair):
    return pair.__closure__[1].cell_contents

Return To Top

(7/24/18) Problem 6

An XOR linked list is a more memory efficient doubly linked list. Instead of each node holding next and prev fields, it holds a field named both, which is an XOR of the next node and the previous node. Implement an XOR linked list; it has an add(element) which adds the element to the end, and a get(index) which returns the node at index.

If using a language that has no pointers (such as Python), you can assume you have access to get_pointer and dereference_pointer functions that converts between nodes and memory addresses.

Return To Top

(10/4/2019) Problem 7

Given the linked list and a positive integer k, rotate the list to the right by k places. For example given the linked list 7 -> 7 -> 3 -> 5 and k=2 it should become 3 -> 5 -> 7 -> 7

Given the linked list 1 -> 2 -> 3 -> 4 -> 5 and k = 3, it should become 3 -> 4 -> 5 -> 1 -> 2.

Problem 6 Solution

Let's look at the structure of the solution:

a -> b -> c -> d -> e, k = 2

becomes

d -> e -> a -> b -> c

To generalize this, we take the k last elements (in order) and move them to the front. We fix the pointers up so that the last element points to the old head, and the kth element's next points to null.

We can accomplish this by using fast and slow pointers.

The basic idea is this. First, advance the fast pointer k steps ahead. Then move the fast and slow pointers together until the fast one hits the end first.

However, to handle the case where k is larger than the length of the linked list itself, we first get the length of the linked list first n, and check k % n first.

Return To Top

About

Just a bunch of practice interview questions that i'll work on.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages