Big-Yellow的算法工程师进阶之路

Big-Yellow的算法工程师进阶之路

一、基础算法

二、基础数据结构

2.1 链表[1]

2.1.1 基础理论

链表是一种以链的形式来存储数据的数据结构。链表的结构:每一个数据都与其后一个数据相连(有时候也与前一个数据相连)。链表中的每个元素都被称为一个结点, 在形状上链表就像自行车链条一样 一节接着一节
链表的优点

  • 1、因为链表是一个链式的数据结构,你可以快速地添加和移除其中的元素。并且这也不需要像数组或者列表那样来重新组织数据。线性的数据结构用链表来实现更加容易。
  • 2、同样因为它的链式结构,链表也不需要一个固定的或者初始的大小。

链表的缺点

  • 1、与数组相比,链表占用更多的内存空间。这是因为你需要一个占用额外内存空间的指针来指向下一个元素。
  • 2、在链表上执行搜索操作非常的慢。不像数组,你不能随机访问链表中的元素

链表使用

  • 1、不知道数据列表中会有多少个元素(这是链表的一个优势 - 添加元素非常简单)。
  • 2、不需要随机访问任何一个元素(与数组不同,你不能在链表中以一个特定的索引访问元素)。
  • 3、要在数据列表的中间插入元素。
  • 4、你需要以常数式时间从数据列表中插入和删除元素(与数组不同,你不需要先移动数据列表中的每一个其他元素)。

2.1.2 Python实现[2]

只需要意识到你将要添加到链表中的每一个元素都只是一个结点(就像链条中的一环)。头结点(链表中的第一个结点)的特殊之处在于你先确定一个头结点,然后再开始向它后面添加其他结点

1、单向链表****

  • 创建链表
创建链表
class Node:
    def __init__(self, val):
        self.val = val # 存放数据
        self.next = None # 指向下一个节点
  • 定义链表
定义链表
class SingleLinkList(object):
    """单链表"""
    def __init__(self):
        self.head = None
    
    def is_empty(self):
        """判断链表是否为空"""
        return self.head is None
    def length(self):
        """链表长度"""
        cur = self.head
        count = 0
        while cur:
            coun +=1
            cur = self.head.next
        return count
    def item(self):
        """遍历链表"""
        cur = self.head
        while cur:
            yield cur.val
            # 指针下移
            cur = cur.next
    def add(self, val):
        """向链表头部添加节点"""
        node = Node(val)
        node.next = self.head
        self.head = node
    def append(self, val):
        """向链表尾部添加节点"""
        node = Node(val)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next:
                cur = cur.next
            cur.next = node
    def insert(self, index, val):
        """指定位置插入元素"""
        if index <0:
            self.add(val)
        else:
            node = Node(val)
            cur = self.head
            for i in range(index- 1):
                cur = cur.next
            node.next = cur.next
            cur.next = node
    def remove(self, val):
        """删除节点"""
        cur = self.head
        pre = None
        while cur:
            if cur.next == val:
                if not pre:
                    self.head = cur.next
                else:
                    pre.next = cur.next
                return True
            else:
                pre = cur
                cur = cur.next
        
if __name__ == '__main__':
    link_list = SingleLinkList()
    # 向链表尾部添加数据
    for i in range(5):
        link_list.append(i)
    # 向头部添加数据
    link_list.add(6)
    # 遍历链表数据
    for i in link_list.item():
        print(i, end='\t')
    # 链表数据插入数据
    link_list.insert(3, 9)
    print('\n', list(link_list.item()))
    # 删除链表数据
    link_list.remove(0)
    # 查找链表数据
    print(link_list.find(4))

2.1.3 LeetCode习题

题目来源:
1、LeetCode官网
2、代码随想录

链表题解关键是断开连接然后去连接下一个,适当的临时节点(哨兵),防止后续指向不明确(不让指针迷路)

解决代码及思路
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        """问题一""""
        pre, cur = head, None
        while pre is not None:
            tmp = pre.next
            pre.next = cur
            cur = pre
            pre = tmp
        return cur
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        """问题二""""
        if head is None or head.next is None:
            return head
        pre, cur = head, head.next
        mind = pre.next.next
        cur.next = pre
        pre.next = self.swapPairs(mind)
        return cur
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        """问题二
        先把所有的点都丢到哈希表中,而后通过哈希表找到要删除的元素,而后删除
        """
        pre = ListNode(0, head)
        node = pre
        index = 0
        tmp_list = {}
        while node:
            tmp_list[index]= node
            node = node.next
            index +=1
        tmp_list[index- n- 1].next = tmp_list[index- n].next
        return pre.next
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        """问题三
        构建哈希表,把一个链表元素都丢到哈希表里面,然后去递归另外一个看看是否在设置的哈希表中
        """
        preA, preB = ListNode(next=headA), ListNode(next=headB)
        mapB = set()
        while preB.next:
            mapB.add(preB.next)
            preB = preB.next
        while preA.next:
            if preA.next in setB:
                return preA.next
            preA = preA.next
        return None
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        """问题四
        链表查找:还是哈希表,判断在/不在
        """
        pre = head
        map_list = set()
        while pre:
            if pre in map_list:
                return pre
            map_list.add(pre)
            pre = pre.next
        return None 

2.2 哈希表

2.2.3 LeetCode习题

解决代码及思路

三、🐉LeetCode推荐习题

1、LRU缓存

🔗题目链接https://leetcode.cn/problems/lru-cache/description/
📃题目描述:请你设计并实现一个满足LRU (最近最少使用) 缓存 约束的数据结构。实现LRUCache 类:

  • LRUCache(int capacity) 以正整数作为容量capacity初始化LRU缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回\(-1\)
  • void put(int key, int value)如果关键字 key 已经存在,则变更其数据值value;如果不存在,则向缓存中插入该组key-value。如果插入操作导致关键字数量超过capacity,则应该 逐出 最久未使用的关键字。

函数get和put必须以\(O(1)\)的平均时间复杂度运行。

️解题思路:定义一个字典 对象去对值进行存储,因为put或者get操作都会对存储的对象进行修改,因此在执行上述两步操作之后需要对循序进行修改。对于get操作就比较简单:只需要比较是否在字典存在,存在则返回值并且修改顺序,反之则输出null。(利用get函数即可)。对于put操作就复杂一点:首先判断是否存在:存在则需要将其放置都字典最后;不存在则需要判断是否超过了定义的capacity如果没有就直接加入即可,有的话就需要将字典第一个元素进行替换(对于获取字典第一个元素可以使用生成器iter(),生成器里面都是从最开始位置开始)。

问题描述
20240225212105
Code
class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.data = dict()
    def get(self, key: int) -> int:
        s = self.data.get(key, -1)
        if s != -1:
            self.data.pop(key)
            self.data[key]= s
        return s
    def put(self, key: int, value: int) -> None:
        if key in self.data:
            self.data.pop(key)
            self.data[key] = value
        else:
            # 不在 data 里面的话:1、超过了容量,那么进行替代;2、没有超过容量:那么添加
            if len(self.data) < self.capacity:
                k = next(iter(self.data))
                self.data.pop(k)
                self.data[key] = value
            else:
                self.data[key] = value

2、背包问题

参考


  1. https://www.freecodecamp.org/chinese/news/introduction-to-linked-lists-in-python/ ↩︎

  2. https://zhuanlan.zhihu.com/p/60057180 ↩︎

posted @ 2024-02-25 08:40  Big-Yellow-J  阅读(22)  评论(0编辑  收藏  举报