算法:栈和队列和链表

栈和队列

基本性质

  • 先进后出
  • 实现方式:有数组和链表两种形式。数组实现较容易,链表实现较复杂。
  • 基本操作:top / pop / push / size 操作,时间复杂度 O(1)
  • 深度优先(DFS)使用栈实现

队列

  • 先进先出
  • 实现方式:有数组和链表两种形式。数组实现较容易,链表实现较复杂。
  • 基本操作:top / pop / push / size 操作,时间复杂度 O(1)
  • 宽度优先(BFS)使用队列实现

双端队列

  • 首尾均可以压入和弹出元素

优先级队列

  • 根据元素的优先级,决定元素的弹出顺序
  • 堆结构

经典题目

  1. 最小栈
    思路:辅助栈。
    lc 155 https://leetcode.cn/problems/min-stack/
  2. 基于栈实现队列
    思路:两个栈,一个负责压入栈,一个负责弹出栈。
    https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/
  3. 实现栈的逆序,只能用递归操作和栈本身的函数实现。不能使用其它数据结构。
    思路:利用递归函数的函数栈。
    牛客:https://www.nowcoder.com/practice/1de82c89cc0e43e9aa6ee8243f4dbefd?tpId=101&rp=1&ru=%2Fexam%2Foj%2Fta&qru=%2Fexam%2Foj%2Fta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26pageSize%3D50%26search%3Dkmp%26tpId%3D101%26type%3D101&difficulty=&judgeStatus=&tags=&title=%E6%A0%88&gioEnter=menu
  4. 将栈中从顶到底按照从大到小排序,只许申请一个栈,除此之外可以申请新的变量,但不能申请额外的数据结构。
    思路:汉诺塔原理
    https://leetcode.cn/problems/sort-of-stacks-lcci/
    https://www.nowcoder.com/practice/ff8cba64e7894c5582deafa54cca8ff2?tpId=101&rp=1&ru=%2Fexam%2Foj%2Fta&qru=%2Fexam%2Foj%2Fta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26pageSize%3D50%26search%3Dkmp%26tpId%3D101%26type%3D101&difficulty=&judgeStatus=&tags=&title=%E6%A0%88&gioEnter=menu
  5. 滑动窗口的最大值
    思路:双端队列
    https://leetcode.cn/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/
  6. 给定一个没有重复元素的数组arr,写出生成这个数组maxTree的函数。要求如果数组长度为N,时间复杂度为O(N),额外空间复杂度为O(N)。
    maxTree是一个二叉树,数组的每一个值对应二叉树的一个节点。
    包括maxTree树在内,且在其中的每一棵子树上,值最大的节点都是树的头。
    https://leetcode.cn/problems/maximum-binary-tree/

链表

链表:

  • 算法实现上难度较低,主要是考察代码实现的能力
  • 链表的存储空间是临时分配的,不保证空间上的连续性。
  • 链表的分类
    • 从连接方向上:单链表、双链表
    • 按照有环、无环分类:普通链表、循环链表
  • 链表插入、链表删除、链表翻转
  1. 单链表,反转链表
    https://leetcode.cn/problems/reverse-linked-list/
    def reverseList(self, head: ListNode) -> ListNode:
        # 链表为空时直接返回
        if not head:
            return None
        # 链表不为空时,逐个反转
        prev = None
        cur = head
        while cur:
            nextPtr = cur.next
            cur.next = prev
            prev = cur
            cur = nextPtr
        return prev
  1. 向有序的环形链表中插入节点
    https://leetcode.cn/problems/insert-into-a-sorted-circular-linked-list/
"""注意边界条件!!!!"""
    def insert(self, head, insertVal):
        """
        :type head: Node
        :type insertVal: int
        :rtype: Node
        """
        node = Node(insertVal)
        if not head:
            node.next = node
            return node
        else:
            pre = head
            cur = head.next
            # 首先找到head节点
            while cur != head and pre!=cur and pre.val <= cur.val:
                pre = cur
                cur = cur.next
            newHead = cur
            # 从新head开始往后找insert的位置
            pre = newHead
            cur = newHead.next
            while cur != newHead and pre != cur and pre.val <= cur.val:
                if pre.val <= insertVal and insertVal <= cur.val:
                    # 插入insertVal
                    pre.next = node
                    node.next = cur
                    return head
                pre = cur
                cur = cur.next
            # 到达循环链表的尾部-头部交界处
            pre.next = node
            node.next = cur
            return head
  1. 给定单链表中节点node,但是不给头节点head,如何删除node节点?时间复杂度O(1)。
    作为面试题简单,但在工程实践中存在问题
    https://leetcode.cn/problems/delete-node-in-a-linked-list/
    def deleteNode(self, node):
        # 伪删除node点
        node.val = node.next.val
        # 删除node的下一个节点
        node.next = node.next.next
  1. 给定一个链表,再给定一个整数 pivot,请将链表调整为左部分都是值小于 pivot 的节点,中间部分都是值等于 pivot 的节点, 右边部分都是大于 pivot 的节点。
    分成三个小链表,再拼起来。
    https://www.nowcoder.com/practice/04fcabc5d76e428c8100dbd855761778?tpId=101&tqId=33181&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26pageSize%3D50%26search%3D%25E9%2593%25BE%25E8%25A1%25A8%26tpId%3D101%26type%3D101&difficulty=undefined&judgeStatus=undefined&tags=&title=%E9%93%BE%E8%A1%A8
  2. 给定两个有序链表的头节点,打印两个链表公共部分
    https://www.nowcoder.com/practice/8943eea40dbb4185b187d80fd050fee9?tpId=101&tqId=33116&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26pageSize%3D50%26search%3D%25E9%2593%25BE%25E8%25A1%25A8%26tpId%3D101%26type%3D101&difficulty=undefined&judgeStatus=undefined&tags=&title=%E9%93%BE%E8%A1%A8
  3. 每K个节点之间逆序,最后不够K个节点一组,不调整最后几个节点。
    https://leetcode.cn/problems/reverse-nodes-in-k-group/
    def reverseKGroup(self, head, k):
        k_cnt = 0
        prev = None
        cur = head
        k_nextP = head
        nextP = None
        orig_head = head
        # 构建首组反转链表
        while k_nextP:
            if k_cnt < k:
                k_nextP = k_nextP.next
                k_cnt += 1
            if k_cnt == k: #此时k_nextP在下一组的第一个位置
                prev = k_nextP
                while cur and cur != k_nextP:
                    nextP = cur.next
                    cur.next = prev
                    prev = cur
                    cur = nextP
                break
        if k_cnt < k: #首次未进入反转循环
            return head
        elif k_cnt == k and not k_nextP: #首次正好满足一次循环
            return prev
        else:
            init_head = prev
            k_cnt = 0
            while k_nextP:
                if k_cnt < k:
                    k_nextP = k_nextP.next
                    k_cnt += 1
                if k_cnt == k: #此时k_nextP在下一组的第一个位置
                    prev = k_nextP
                    while cur and cur != k_nextP:
                        nextP = cur.next
                        cur.next = prev
                        prev = cur
                        cur = nextP
                    tmp = orig_head.next
                    orig_head.next = prev
                    orig_head = tmp
                    k_cnt = 0
            return init_head

https://www.nowcoder.com/practice/66285653d28b4ed6a15613477670e936?tpId=101&tqId=33187&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26pageSize%3D50%26search%3D%25E9%2593%25BE%25E8%25A1%25A8%26tpId%3D101%26type%3D101&difficulty=undefined&judgeStatus=undefined&tags=&title=%E9%93%BE%E8%A1%A8
8. 给定一个单链表的头节点,再给定一个整数value,将链表中所有等于value的节点删掉。
https://www.nowcoder.com/practice/1a5fd679e31f4145a10d46bb8fd3d211?tpId=101&tqId=33206&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26pageSize%3D50%26search%3D%25E9%2593%25BE%25E8%25A1%25A8%26tpId%3D101%26type%3D101&difficulty=undefined&judgeStatus=undefined&tags=&title=%E9%93%BE%E8%A1%A8
9. 判断链表是否为回文结构。
https://www.nowcoder.com/practice/4b13dff86de64f84ac284e31067b86e2?tpId=101&tqId=33179&rp=1&ru=/exam/oj/ta&qru=/exam/oj/ta&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26pageSize%3D50%26search%3D%25E9%2593%25BE%25E8%25A1%25A8%26tpId%3D101%26type%3D101&difficulty=undefined&judgeStatus=undefined&tags=&title=%E9%93%BE%E8%A1%A8
申请辅助栈

判断链表是否有环,并返回入环的第一个节点?

如何判断两个无环链表是否相交?相交的话,返回第一个相交的节点?

如何判断两个有环链表是否相交?相交的话,返回第一个相交的节点?

如何判断两个单链表是否相交?相交的话,返回第一个相交的节点?

一个链表中,不仅有next还有rand,复制这种含有rand结构的链表。

你可能感兴趣的:(面经笔经,学习笔记,链表,算法,数据结构)