{"id":4433,"date":"2024-10-21T09:17:38","date_gmt":"2024-10-21T09:17:38","guid":{"rendered":"https:\/\/algocademy.com\/blog\/10-unexpected-coding-interview-questions-and-their-solutions\/"},"modified":"2024-10-21T09:17:38","modified_gmt":"2024-10-21T09:17:38","slug":"10-unexpected-coding-interview-questions-and-their-solutions","status":"publish","type":"post","link":"https:\/\/algocademy.com\/blog\/10-unexpected-coding-interview-questions-and-their-solutions\/","title":{"rendered":"10 Unexpected Coding Interview Questions and Their Solutions"},"content":{"rendered":"<p><!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD HTML 4.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/REC-html40\/loose.dtd\"><br \/>\n<html><body><\/p>\n<article>\n<p>Preparing for a coding interview can be a daunting task. While you might be well-versed in common data structures and algorithms, interviewers often throw curveballs to test your problem-solving skills and ability to think on your feet. In this article, we&#8217;ll explore ten unexpected coding interview questions that you might encounter and provide detailed solutions to help you tackle them with confidence.<\/p>\n<h2>1. The Skyline Problem<\/h2>\n<p>This problem is a classic example of a question that seems simple at first glance but requires careful consideration to solve efficiently.<\/p>\n<h3>Question:<\/h3>\n<p>Given a list of buildings where each building is represented by a triplet (left, right, height), where left and right are x-coordinates, and height is the building&#8217;s height, return a list of the key points in the skyline formed by these buildings.<\/p>\n<h3>Solution:<\/h3>\n<p>This problem can be solved using a sweep line algorithm and a priority queue. Here&#8217;s a Python implementation:<\/p>\n<pre><code>import heapq\n\ndef get_skyline(buildings):\n    events = []\n    for l, r, h in buildings:\n        events.append((l, -h, r))  # start of building\n        events.append((r, 0, 0))   # end of building\n    events.sort()\n\n    res = []\n    heap = [(0, float('inf'))]\n    max_height = 0\n\n    for x, neg_h, r in events:\n        if neg_h != 0:\n            heapq.heappush(heap, (neg_h, r))\n        else:\n            while heap[0][1] &lt;= x:\n                heapq.heappop(heap)\n\n        if -heap[0][0] != max_height:\n            max_height = -heap[0][0]\n            res.append([x, max_height])\n\n    return res\n<\/code><\/pre>\n<p>This solution has a time complexity of O(n log n) where n is the number of buildings.<\/p>\n<h2>2. LRU Cache Implementation<\/h2>\n<p>Implementing a Least Recently Used (LRU) cache is a common interview question that tests your understanding of data structures and your ability to optimize for both time and space complexity.<\/p>\n<h3>Question:<\/h3>\n<p>Implement an LRU cache with get and put operations in O(1) time complexity.<\/p>\n<h3>Solution:<\/h3>\n<p>We can use a combination of a hash map and a doubly linked list to achieve O(1) time complexity for both operations:<\/p>\n<pre><code>class Node:\n    def __init__(self, key=0, value=0):\n        self.key = key\n        self.value = value\n        self.prev = None\n        self.next = None\n\nclass LRUCache:\n    def __init__(self, capacity: int):\n        self.capacity = capacity\n        self.cache = {}\n        self.head = Node()\n        self.tail = Node()\n        self.head.next = self.tail\n        self.tail.prev = self.head\n\n    def get(self, key: int) -&gt; int:\n        if key in self.cache:\n            node = self.cache[key]\n            self._remove(node)\n            self._add(node)\n            return node.value\n        return -1\n\n    def put(self, key: int, value: int) -&gt; None:\n        if key in self.cache:\n            self._remove(self.cache[key])\n        node = Node(key, value)\n        self._add(node)\n        self.cache[key] = node\n        if len(self.cache) &gt; self.capacity:\n            lru = self.head.next\n            self._remove(lru)\n            del self.cache[lru.key]\n\n    def _remove(self, node):\n        node.prev.next = node.next\n        node.next.prev = node.prev\n\n    def _add(self, node):\n        node.prev = self.tail.prev\n        node.next = self.tail\n        self.tail.prev.next = node\n        self.tail.prev = node\n<\/code><\/pre>\n<p>This implementation ensures that both get and put operations have O(1) time complexity.<\/p>\n<h2>3. Design a Tiny URL System<\/h2>\n<p>System design questions are becoming increasingly common in coding interviews. This question tests your ability to design a scalable system and consider various trade-offs.<\/p>\n<h3>Question:<\/h3>\n<p>Design a system that generates short URLs from long URLs and vice versa.<\/p>\n<h3>Solution:<\/h3>\n<p>Here&#8217;s a high-level design for a TinyURL system:<\/p>\n<ol>\n<li>Use a hash function to generate a unique short code for each long URL.<\/li>\n<li>Store the mapping between short codes and long URLs in a database.<\/li>\n<li>Implement an API with endpoints for shortening URLs and redirecting short URLs.<\/li>\n<\/ol>\n<p>Here&#8217;s a simple Python implementation of the core functionality:<\/p>\n<pre><code>import hashlib\n\nclass TinyURL:\n    def __init__(self):\n        self.url_to_code = {}\n        self.code_to_url = {}\n\n    def shorten(self, long_url):\n        if long_url in self.url_to_code:\n            return self.url_to_code[long_url]\n\n        code = self._generate_code(long_url)\n        while code in self.code_to_url:\n            code = self._generate_code(code)\n\n        self.url_to_code[long_url] = code\n        self.code_to_url[code] = long_url\n        return code\n\n    def expand(self, short_code):\n        return self.code_to_url.get(short_code, '')\n\n    def _generate_code(self, url):\n        return hashlib.md5(url.encode()).hexdigest()[:6]\n<\/code><\/pre>\n<p>This is a simplified version and doesn&#8217;t address all aspects of a production system, such as handling collisions more robustly or dealing with database scalability.<\/p>\n<h2>4. Implement a Rate Limiter<\/h2>\n<p>Rate limiting is a crucial concept in system design, especially for APIs. This question tests your understanding of distributed systems and concurrency.<\/p>\n<h3>Question:<\/h3>\n<p>Implement a rate limiter that allows n requests per second per user.<\/p>\n<h3>Solution:<\/h3>\n<p>We can use the token bucket algorithm to implement a rate limiter. Here&#8217;s a simple Python implementation:<\/p>\n<pre><code>import time\n\nclass RateLimiter:\n    def __init__(self, capacity, refill_rate):\n        self.capacity = capacity\n        self.refill_rate = refill_rate\n        self.tokens = capacity\n        self.last_refill_time = time.time()\n\n    def allow_request(self):\n        now = time.time()\n        time_passed = now - self.last_refill_time\n        self.tokens = min(self.capacity, self.tokens + time_passed * self.refill_rate)\n        self.last_refill_time = now\n\n        if self.tokens &gt;= 1:\n            self.tokens -= 1\n            return True\n        return False\n\n# Usage\nlimiter = RateLimiter(capacity=10, refill_rate=1)  # 10 requests per second\nfor _ in range(15):\n    print(limiter.allow_request())\n    time.sleep(0.1)\n<\/code><\/pre>\n<p>This implementation allows for a burst of requests up to the capacity, then throttles to the specified rate.<\/p>\n<h2>5. Implement a Thread-Safe Singleton<\/h2>\n<p>This question tests your understanding of design patterns, concurrency, and language-specific features.<\/p>\n<h3>Question:<\/h3>\n<p>Implement a thread-safe singleton pattern in your preferred language.<\/p>\n<h3>Solution:<\/h3>\n<p>Here&#8217;s a thread-safe singleton implementation in Python using a decorator:<\/p>\n<pre><code>import threading\n\ndef singleton(cls):\n    instances = {}\n    lock = threading.Lock()\n\n    def get_instance(*args, **kwargs):\n        if cls not in instances:\n            with lock:\n                if cls not in instances:\n                    instances[cls] = cls(*args, **kwargs)\n        return instances[cls]\n\n    return get_instance\n\n@singleton\nclass MyClass:\n    def __init__(self):\n        self.value = None\n\n    def set_value(self, value):\n        self.value = value\n\n# Usage\ninstance1 = MyClass()\ninstance2 = MyClass()\nprint(instance1 is instance2)  # True\n<\/code><\/pre>\n<p>This implementation ensures that only one instance of the class is created, even in a multi-threaded environment.<\/p>\n<h2>6. Implement a Circular Buffer<\/h2>\n<p>Circular buffers are useful in scenarios with fixed-size buffers, such as in embedded systems or when implementing certain algorithms.<\/p>\n<h3>Question:<\/h3>\n<p>Implement a circular buffer with fixed size that overwrites the oldest data when full.<\/p>\n<h3>Solution:<\/h3>\n<p>Here&#8217;s a Python implementation of a circular buffer:<\/p>\n<pre><code>class CircularBuffer:\n    def __init__(self, size):\n        self.buffer = [None] * size\n        self.size = size\n        self.head = 0\n        self.tail = 0\n        self.count = 0\n\n    def push(self, item):\n        if self.count == self.size:\n            self.head = (self.head + 1) % self.size\n        else:\n            self.count += 1\n\n        self.buffer[self.tail] = item\n        self.tail = (self.tail + 1) % self.size\n\n    def pop(self):\n        if self.count == 0:\n            return None\n\n        item = self.buffer[self.head]\n        self.head = (self.head + 1) % self.size\n        self.count -= 1\n        return item\n\n    def __len__(self):\n        return self.count\n\n    def __str__(self):\n        return str(self.buffer)\n\n# Usage\ncb = CircularBuffer(5)\nfor i in range(7):\n    cb.push(i)\nprint(cb)  # [5, 6, 2, 3, 4]\nprint(cb.pop())  # 2\nprint(cb)  # [5, 6, None, 3, 4]\n<\/code><\/pre>\n<p>This implementation efficiently manages the buffer, overwriting the oldest data when the buffer is full.<\/p>\n<h2>7. Implement a Basic Garbage Collector<\/h2>\n<p>While most modern languages have built-in garbage collection, understanding how it works is crucial for systems programming and can be asked in interviews for more low-level positions.<\/p>\n<h3>Question:<\/h3>\n<p>Implement a basic mark-and-sweep garbage collector for a simple object system.<\/p>\n<h3>Solution:<\/h3>\n<p>Here&#8217;s a simplified implementation of a mark-and-sweep garbage collector in Python:<\/p>\n<pre><code>class Object:\n    def __init__(self):\n        self.marked = False\n        self.children = []\n\nclass GarbageCollector:\n    def __init__(self):\n        self.objects = []\n\n    def allocate(self):\n        obj = Object()\n        self.objects.append(obj)\n        return obj\n\n    def add_root(self, obj):\n        self.objects.append(obj)\n\n    def mark(self, obj):\n        if obj.marked:\n            return\n        obj.marked = True\n        for child in obj.children:\n            self.mark(child)\n\n    def sweep(self):\n        self.objects = [obj for obj in self.objects if obj.marked]\n        for obj in self.objects:\n            obj.marked = False\n\n    def collect(self):\n        for obj in self.objects:\n            if hasattr(obj, 'root') and obj.root:\n                self.mark(obj)\n        self.sweep()\n\n# Usage\ngc = GarbageCollector()\nroot = gc.allocate()\nroot.root = True\nchild1 = gc.allocate()\nchild2 = gc.allocate()\nroot.children = [child1, child2]\n\nprint(len(gc.objects))  # 3\ngc.collect()\nprint(len(gc.objects))  # 3\n\nchild1.children = [gc.allocate()]\nprint(len(gc.objects))  # 4\ngc.collect()\nprint(len(gc.objects))  # 4\n\nroot.children = [child1]\ngc.collect()\nprint(len(gc.objects))  # 3\n<\/code><\/pre>\n<p>This implementation demonstrates the basic principles of mark-and-sweep garbage collection, though real-world garbage collectors are much more complex and optimized.<\/p>\n<h2>8. Implement a Basic Regular Expression Matcher<\/h2>\n<p>Understanding how regular expressions work under the hood can be valuable, especially for roles involving text processing or compiler design.<\/p>\n<h3>Question:<\/h3>\n<p>Implement a basic regular expression matcher that supports &#8216;.&#8217; (matches any single character) and &#8216;*&#8217; (matches zero or more of the preceding element).<\/p>\n<h3>Solution:<\/h3>\n<p>Here&#8217;s a recursive implementation of a basic regex matcher in Python:<\/p>\n<pre><code>def match(text, pattern):\n    if not pattern:\n        return not text\n    \n    first_match = bool(text) and pattern[0] in {text[0], '.'}\n    \n    if len(pattern) &gt;= 2 and pattern[1] == '*':\n        return (match(text, pattern[2:]) or\n                (first_match and match(text[1:], pattern)))\n    else:\n        return first_match and match(text[1:], pattern[1:])\n\n# Usage\nprint(match(\"aa\", \"a\"))  # False\nprint(match(\"aa\", \"a*\"))  # True\nprint(match(\"ab\", \".*\"))  # True\nprint(match(\"aab\", \"c*a*b\"))  # True\n<\/code><\/pre>\n<p>This implementation handles the basic cases of &#8216;.&#8217; and &#8216;*&#8217;, but doesn&#8217;t support more complex regex features like grouping or alternation.<\/p>\n<h2>9. Implement a Basic JSON Parser<\/h2>\n<p>Parsing is a fundamental concept in computer science, and implementing a basic parser tests your ability to work with grammars and recursive structures.<\/p>\n<h3>Question:<\/h3>\n<p>Implement a basic JSON parser that can handle strings, numbers, booleans, null, arrays, and objects.<\/p>\n<h3>Solution:<\/h3>\n<p>Here&#8217;s a simplified JSON parser implementation in Python:<\/p>\n<pre><code>import re\n\ndef parse_json(s):\n    def parse_value():\n        nonlocal i\n        if s[i] == '{':\n            return parse_object()\n        elif s[i] == '[':\n            return parse_array()\n        elif s[i] == '\"':\n            return parse_string()\n        elif s[i].isdigit() or s[i] == '-':\n            return parse_number()\n        elif s[i:i+4] == 'true':\n            i += 4\n            return True\n        elif s[i:i+5] == 'false':\n            i += 5\n            return False\n        elif s[i:i+4] == 'null':\n            i += 4\n            return None\n\n    def parse_object():\n        nonlocal i\n        obj = {}\n        i += 1  # Skip '{'\n        while s[i] != '}':\n            key = parse_string()\n            i += 1  # Skip ':'\n            value = parse_value()\n            obj[key] = value\n            if s[i] == ',':\n                i += 1\n        i += 1  # Skip '}'\n        return obj\n\n    def parse_array():\n        nonlocal i\n        arr = []\n        i += 1  # Skip '['\n        while s[i] != ']':\n            value = parse_value()\n            arr.append(value)\n            if s[i] == ',':\n                i += 1\n        i += 1  # Skip ']'\n        return arr\n\n    def parse_string():\n        nonlocal i\n        i += 1  # Skip opening quote\n        start = i\n        while s[i] != '\"':\n            if s[i] == '\\\\':\n                i += 1\n            i += 1\n        result = s[start:i]\n        i += 1  # Skip closing quote\n        return result\n\n    def parse_number():\n        nonlocal i\n        start = i\n        while i &lt; len(s) and (s[i].isdigit() or s[i] in '.-+eE'):\n            i += 1\n        return float(s[start:i])\n\n    i = 0\n    return parse_value()\n\n# Usage\njson_str = '{\"name\": \"John\", \"age\": 30, \"city\": \"New York\", \"hobbies\": [\"reading\", \"swimming\"]}'\nparsed = parse_json(json_str)\nprint(parsed)\n<\/code><\/pre>\n<p>This parser handles basic JSON structures but doesn&#8217;t include full error handling or support for all JSON escape sequences.<\/p>\n<h2>10. Implement a Basic Neural Network<\/h2>\n<p>With the increasing importance of machine learning, understanding the basics of neural networks can be valuable in many software engineering roles.<\/p>\n<h3>Question:<\/h3>\n<p>Implement a basic feedforward neural network with one hidden layer and train it on a simple dataset.<\/p>\n<h3>Solution:<\/h3>\n<p>Here&#8217;s a simple implementation of a neural network with one hidden layer in Python, using numpy for efficient matrix operations:<\/p>\n<pre><code>import numpy as np\n\nclass NeuralNetwork:\n    def __init__(self, input_size, hidden_size, output_size):\n        self.W1 = np.random.randn(input_size, hidden_size)\n        self.b1 = np.zeros((1, hidden_size))\n        self.W2 = np.random.randn(hidden_size, output_size)\n        self.b2 = np.zeros((1, output_size))\n\n    def sigmoid(self, x):\n        return 1 \/ (1 + np.exp(-x))\n\n    def sigmoid_derivative(self, x):\n        return x * (1 - x)\n\n    def forward(self, X):\n        self.z1 = np.dot(X, self.W1) + self.b1\n        self.a1 = self.sigmoid(self.z1)\n        self.z2 = np.dot(self.a1, self.W2) + self.b2\n        self.a2 = self.sigmoid(self.z2)\n        return self.a2\n\n    def backward(self, X, y, output):\n        self.dZ2 = output - y\n        self.dW2 = np.dot(self.a1.T, self.dZ2)\n        self.db2 = np.sum(self.dZ2, axis=0, keepdims=True)\n        self.dZ1 = np.dot(self.dZ2, self.W2.T) * self.sigmoid_derivative(self.a1)\n        self.dW1 = np.dot(X.T, self.dZ1)\n        self.db1 = np.sum(self.dZ1, axis=0)\n\n    def train(self, X, y, epochs, learning_rate):\n        for _ in range(epochs):\n            output = self.forward(X)\n            self.backward(X, y, output)\n            self.W1 -= learning_rate * self.dW1\n            self.b1 -= learning_rate * self.db1\n            self.W2 -= learning_rate * self.dW2\n            self.b2 -= learning_rate * self.db2\n\n# Usage\nX = np.array([[0, 0, 1], [0, 1, 1], [1, 0, 1], [1, 1, 1]])\ny = np.array([[0], [1], [1], [0]])\n\nnn = NeuralNetwork(3, 4, 1)\nnn.train(X, y, epochs=10000, learning_rate=0.1)\n\n# Test\nprint(nn.forward(np.array([[1, 1, 0]])))\n<\/code><\/pre>\n<p>This implementation demonstrates the basic concepts of feedforward neural networks and backpropagation, though it&#8217;s simplified and not optimized for large-scale problems.<\/p>\n<h2>Conclusion<\/h2>\n<p>These ten unexpected coding interview questions cover a wide range of topics, from system design to low-level programming concepts. While you may not encounter these exact questions in your interviews, understanding the principles behind them will help you tackle similar challenges.<\/p>\n<p>Remember, the key to succeeding in coding interviews is not just knowing the solutions to specific problems, but understanding the underlying concepts and being able to apply them to new situations. Practice regularly, focus on problem-solving skills, and don&#8217;t be afraid to think outside the box during your interviews.<\/p>\n<p>Good luck with your coding interviews!<\/p>\n<\/article>\n<p><\/body><\/html><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Preparing for a coding interview can be a daunting task. While you might be well-versed in common data structures and&#8230;<\/p>\n","protected":false},"author":1,"featured_media":4432,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[],"class_list":["post-4433","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-problem-solving"],"_links":{"self":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/4433"}],"collection":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/comments?post=4433"}],"version-history":[{"count":0,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/4433\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media\/4432"}],"wp:attachment":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media?parent=4433"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/categories?post=4433"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/tags?post=4433"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}