Python技术迷

女朋友没上过班,表示以后也不想上班,让我包养,就是长得漂亮,该怎么劝她,感觉我一个人抗风险能力。。。

我看到这个问题的时候,简直忍不住笑了。

感觉你在这段感情中,也有点像在debug一个“死循环”,明明觉得已经处理好所有问题,但对方总是返回同样的错误。

至于女朋友是“巨婴”,不想上班,我觉得吧,首先得问问自己:你能接受她一直这样“住在你代码里的bug”吗?

Image

她不想上班,可能只是缺乏经济独立感,不是每个人都天生能主动去面对职场的压力,特别是她从来没有上过班。

你要了解她是不是仅仅对工作的恐惧,还是根本没兴趣。如果她只是缺乏自信,可以从帮她寻找兴趣爱好入手,给她提供一些帮助,培养她的独立性。

如果她就是不想上班,考虑一下你们的未来规划:如果你未来会继续“一个人扛风险”,是不是能承受得住?不过,最重要的,还是沟通。

毕竟,感情这事儿,不能一直单方面修复bug,得共同debug才行。

【备注:文末可领最新资料】

算法题:LRU 缓存

最近看到一个挺有意思的算法题——LRU缓存,想分享一下我的思考过程。

LRU(Least Recently Used,最近最少使用)缓存策略是一种经典的缓存淘汰机制,用来在缓存空间有限的情况下,淘汰掉那些最久未使用的数据。

LRU缓存的实现其实涉及到两个主要的操作:插入数据和删除数据。

我们需要在有限的缓存空间内,快速找到最少使用的数据并将其移除,同时确保能快速地查找、更新或者插入数据。

这要求我们不仅要有合适的数据结构支持,还要考虑算法的时间复杂度,以确保程序的高效运行。

那么,LRU缓存的核心思想就是维护一个按照使用频率排序的数据结构,最常用的数据放在前面,最久未使用的数据放在后面。

当缓存空间满时,删除最久未使用的数据。接下来,我会用 Python 来实现一个 LRU 缓存。

为了高效地支持这两个操作,我们需要用到两个数据结构:

  1. 哈希表(Dictionary):可以让我们在常数时间内 O(1) 查找、插入数据。
  2. 双向链表(Doubly Linked List):在双向链表中,插入和删除节点的时间复杂度是 O(1)。我们可以通过双向链表来维护数据的顺序,将最近访问的数据放在链表头部,最久未访问的数据放在链表尾部。

步骤:

  1. 哈希表 存储数据,键是缓存数据的关键字,值是缓存的内容。这样可以快速访问。
  2. 双向链表 用来表示数据的访问顺序,链表的头部是最近使用的数据,尾部是最久未使用的数据。当缓存满了,就删除尾部的节点。

在代码实现时,我们需要设计一个 LRUCache 类,这个类包含以下主要操作:

  • get(key):获取缓存的值,如果存在则返回,若不存在则返回 -1。
  • put(key, value):将数据插入缓存。如果缓存满了,删除最久未使用的项。

实现这个类时,我们需要在插入和删除时维护双向链表的顺序,确保最常用的数据总是在链表的头部。

代码实现:

classDListNode:
def__init__(self, key=0, value=0):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None

classLRUCache:

def__init__(self, capacity: int):
        self.capacity = capacity
        self.cache = {}  # 用哈希表存储缓存内容
        self.head, self.tail = DListNode(), DListNode()  # 伪头和伪尾
        self.head.next = self.tail
        self.tail.prev = self.head

def_remove(self, node: DListNode):
"""删除节点node"""
        prev, _next = node.prev, node.next
        prev.next = _next
        _next.prev = prev

def_insert(self, node: DListNode):
"""在头部插入节点node"""
        node.prev = self.head
        node.next = self.head.next
        self.head.next.prev = node
        self.head.next = node

defget(self, key: int) -> int:
"""获取缓存的值"""
if key in self.cache:
            node = self.cache[key]
# 移动到头部
            self._remove(node)
            self._insert(node)
return node.value
return-1

defput(self, key: int, value: int) -> None:
"""插入数据到缓存"""
if key in self.cache:
# 如果存在,更新值并移动到头部
            self._remove(self.cache[key])
        node = DListNode(key, value)
        self.cache[key] = node
        self._insert(node)

if len(self.cache) > self.capacity:
# 缓存满了,删除尾部最久未使用的数据
            tail = self.head.next
            self._remove(tail)
del self.cache[tail.key]

解析:

  1. 双向链表:我们使用了一个伪头节点和一个伪尾节点,分别表示链表的头部和尾部。所有的节点插入到头部,最常用的节点总是出现在链表的头部,最久未使用的节点总是出现在尾部。

  2. _remove 和 _insert 方法:这两个方法分别用于从链表中删除节点和将节点插入到链表的头部。这是 LRU 缓存的关键所在,保证了我们在插入和删除节点时能在 O(1) 时间复杂度内进行。

  3. 哈希表:哈希表 self.cache 用来存储数据的键值对,使得我们可以在常数时间内 O(1) 查找到缓存中的数据。

  4. get 方法:每次访问缓存时,我们先检查数据是否存在。如果存在,就将它移到头部表示最近使用,并返回值。如果不存在,返回 -1。

  5. put 方法:插入数据时,如果缓存中已经有这个键值对,则更新其值,并将节点移动到头部。如果缓存已满,我们就删除链表尾部的节点,也就是最久未使用的节点。

时间复杂度:

  • get 操作:O(1)
  • put 操作:O(1)

由于我们使用了哈希表来存储数据,并通过双向链表来维护数据的访问顺序,所有操作都可以在常数时间内完成,这使得我们的实现非常高效。

LRU 缓存的实现是一个经典的面试题,考察的是我们对数据结构和算法的理解以及如何高效实现缓存淘汰策略。

通过哈希表和双向链表的组合,我们能够实现一个既高效又简洁的 LRU 缓存。

最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek

也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。

对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
🔥虎哥私藏精品 热门推荐🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》。

资料包含了《IDEA视频教程》、《最全python面试题库》、《最全项目实战源码及视频》及《毕业设计系统源码》,总量高达650GB,全部免费领取