📜  Goibibo 面试经历 |设置 3(1)

📅  最后修改于: 2023-12-03 15:15:21.893000             🧑  作者: Mango

Goibibo 面试经历 |设置 3

本文记录了笔者在参加 Goibibo 公司的面试过程中所获得的经验以及面试题目。

面试流程

Goibibo 的面试流程分为以下几个环节:

  1. HR 面试
  2. 技术面试(可能需要多次)
  3. 负责人面试
  4. CEO 面试

笔者本次参加的是第二次技术面试。

技术面试

本轮面试主要考察的是算法和数据结构方面的知识,具体题目如下:

  1. 给定一个二叉树,求树的最大深度。
  2. 给定一个字符串和一个模式串,利用动态规划算法判断是否匹配。
  3. 给定两个有序数组,合并成一个有序数组。
  4. 设计一个 LRU 缓存系统,实现 get 和 set 方法。
题目解析
  1. 首先想到使用递归来求解二叉树的最大深度。如果当前节点为空,则返回 0;否则,返回左右子树的最大深度加上自身的 1。代码如下:
def max_depth(root):
    if root is None:
        return 0
    left_depth = max_depth(root.left)
    right_depth = max_depth(root.right)
    return max(left_depth, right_depth) + 1
  1. 利用动态规划算法判断字符串和模式串是否匹配是一个经典的问题。首先需要定义状态,然后给出状态转移方程。

定义状态 $dp[i][j]$ 表示字符串前 $i$ 个字符和模式串前 $j$ 个字符是否匹配。状态转移方程如下:

if pattern[j] == '?' or pattern[j] == string[i]:
    dp[i][j] = dp[i - 1][j - 1]
elif pattern[j] == '*':
    dp[i][j] = dp[i][j - 1] or dp[i - 1][j]

其中,当模式串当前字符为 '?' 或和字符串当前字符相同时,状态转移方程为 $dp[i][j] = dp[i-1][j-1]$;当模式串当前字符为 '*' 时,状态转移方程为 $dp[i][j] = dp[i][j-1] \ or \ dp[i-1][j]$。最终结果为 $dp[n][m]$,其中 $n$ 和 $m$ 分别为字符串和模式串的长度。完整代码如下:

def is_match(string, pattern):
    m, n = len(string), len(pattern)
    dp = [[False] * (n + 1) for _ in range(m + 1)]
    dp[0][0] = True

    for i in range(1, n + 1):
        if pattern[i-1] == '*':
            dp[0][i] = dp[0][i-1]

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if pattern[j-1] == '?' or pattern[j-1] == string[i-1]:
                dp[i][j] = dp[i-1][j-1]
            elif pattern[j-1] == '*':
                dp[i][j] = dp[i][j-1] or dp[i-1][j]
    
    return dp[m][n]
  1. 给定两个有序数组,合并成一个有序数组可以用归并排序算法实现。具体步骤是将两个数组合并成一个数组,然后对这个数组进行排序。代码如下:
def merge_sort(nums1, nums2):
    m, n = len(nums1), len(nums2)
    result = [0] * (m + n)
    i, j, k = 0, 0, 0

    while i < m and j < n:
        if nums1[i] < nums2[j]:
            result[k] = nums1[i]
            i += 1
        else:
            result[k] = nums2[j]
            j += 1
        k += 1

    while i < m:
        result[k] = nums1[i]
        i += 1
        k += 1

    while j < n:
        result[k] = nums2[j]
        j += 1
        k += 1

    return result
  1. 设计一个 LRU 缓存系统,实现 get 和 set 方法可以用哈希表和双向链表实现。具体步骤是:用哈希表存储数据,其中 key 是元素的值,value 是元素的指针;用双向链表记录元素的访问顺序,最近访问的元素在链表的头部,最久没有访问的元素在链表的尾部。代码如下:
class LRUCache:
    def __init__(self, capacity):
        self.capacity = capacity
        self.cache = {}
        self.head = ListNode(0)
        self.tail = ListNode(0)
        self.head.next = self.tail
        self.tail.prev = self.head

    def get(self, key):
        if key in self.cache:
            node = self.cache[key]
            self._remove(node)
            self._add(node)
            return node.val
        else:
            return -1

    def put(self, key, value):
        if key in self.cache:
            node = self.cache[key]
            node.val = value
            self._remove(node)
            self._add(node)
        else:
            if len(self.cache) == self.capacity:
                self.cache.pop(self.tail.prev.key)
                self._remove(self.tail.prev)
            node = ListNode(value)
            node.key = key
            self.cache[key] = node
            self._add(node)

    def _remove(self, node):
        prev = node.prev
        next = node.next
        prev.next = next
        next.prev = prev

    def _add(self, node):
        head_next = self.head.next
        self.head.next = node
        node.prev = self.head
        node.next = head_next
        head_next.prev = node

class ListNode:
    def __init__(self, val=0):
        self.val = val
        self.prev = None
        self.next = None
        self.key = None
总结

本次面试中,笔者收获了很多关于算法和数据结构的知识。同时,也对面试过程中的应答技巧和沟通能力有了更深入的认识。希望以上内容能够对读者有所帮助。