📜  Xoriant 面试经历 |第 3 组(校园内)(1)

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

Xoriant 面试经历 | 第 3 组(校园内)

本文主要介绍本人在 Xoriant 校园招聘中第三组面试的经历。在此提供面试题目,以及我的解答过程和思路,希望能够对读者有所帮助。

面试题目
  1. 实现一个基于链表的 LRU 缓存。
  2. 对于一个给定的有序数组,实现一个算法返回两个数字的下标,这两个数字加起来等于一个给定的目标值。
  3. 给定一个字符串和一个字符集,实现一个算法返回这个字符串中,含有字符集中所有字符的最短子串。
解答过程
实现一个基于链表的 LRU 缓存
class LinkedList:
    class Node:
        def __init__(self, key, val):
            self.key = key
            self.val = val
            self.next = None
            self.prev = None

    def __init__(self, capacity):
        self.capacity = capacity
        self.dummy_head = self.Node(None, None)
        self.dummy_tail = self.Node(None, None)
        self.dummy_head.next = self.dummy_tail
        self.dummy_tail.prev = self.dummy_head
        self.size = 0
        self.cache = {}

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

    def _insert(self, node):
        node.next = self.dummy_head.next
        node.prev = self.dummy_head
        node.next.prev = node
        node.prev.next = node

    def get(self, key):
        node = self.cache.get(key)
        if not node:
            return -1
        self._remove(node)
        self._insert(node)
        return node.val

    def put(self, key, val):
        node = self.cache.get(key)
        if node:
            self._remove(node)
            node.val = val
        else:
            node = self.Node(key, val)
            self.cache[key] = node
            if self.size == self.capacity:
                to_remove = self.dummy_tail.prev
                self._remove(to_remove)
                del self.cache[to_remove.key]
            self.size += 1
        self._insert(node)

我们可以使用一个双向链表来维护 LRU 缓存,并在字典中存储每个键对应的节点。在访问键时,我们首先在字典中查找对应的节点,如果找不到则返回 -1。如果找到了,我们将节点从链表中删除,并插入到链表的头部,以更新它的访问位置。如果节点不存在,则创建一个新节点,并将其插入到链表头部,将其添加到字典中。在插入之前,我们删除最后一个节点以确保不超过容量。

时间复杂度:O(1)

空间复杂度:O(n)

实现一个算法返回两个数字的下标,这两个数字加起来等于一个给定的目标值
def twoSum(nums, target):
    complement_map = {}
    for i, num in enumerate(nums):
        complement = target - num
        if complement in complement_map:
            return [complement_map[complement], i]
        complement_map[num] = i
    return []

我们可以使用哈希表来存储每个数及其对应的下标,然后在迭代中查找补数是否在哈希表中存在。如果存在,则返回两个数的下标。

时间复杂度:O(n)

空间复杂度:O(n)

实现一个算法返回这个字符串中,含有字符集中所有字符的最短子串
def minWindow(s, t):
    counter = {}
    for char in t:
        counter[char] = counter.get(char, 0) + 1
    required = len(counter)
    left, right = 0, 0
    formed = 0
    window_counts = {}
    ans = float('inf'), None, None
    while right < len(s):
        char = s[right]
        window_counts[char] = window_counts.get(char, 0) + 1
        if char in counter and window_counts[char] == counter[char]:
            formed += 1
        while left <= right and formed == required:
            char = s[left]
            if right - left + 1 < ans[0]:
                ans = (right - left + 1, left, right)
            window_counts[char] -= 1
            if char in counter and window_counts[char] < counter[char]:
                formed -= 1
            left += 1
        right += 1
    return "" if ans[0] == float('inf') else s[ans[1]:ans[2] + 1]

我们可以使用滑动窗口的方法来在 O(n) 的时间复杂度内解决此问题。首先,我们创建一个字典来存储字符集 t 中每个字符出现的次数。然后使用两个指针 left 和 right 来指示窗口的左右边界。我们将 right 指针向右移动,直到窗口包含字符集 t 中的所有字符。当窗口中的字符满足要求时,我们可以更新答案并尝试缩小窗口大小。为了缩小窗口,我们移动左指针并从窗口中删除最左边的字符。每次移动左指针时,我们检查窗口中是否仍然存在 t 中的所有字符。如果窗口中存在 t 中的所有字符,则我们继续移动左指针来寻找可能更短的窗口。

时间复杂度:O(|S| + |T|)

空间复杂度:O(|S| + |T|)