栈,队列,链表

最小栈

最小栈

  • 双栈

字符匹配

匹配

  • 使用到了unordered_map

字符串解码

字符串解码

  • 用vector操作方便得多

单调栈

每日温度

  • 往后数第一个比自己大的数

柱状图面积

  • 两个单调栈:分别往两边数,找到比自己小的数,确定区间

队列

链表

头插法

删除元素k

倒转链表

#include <iostream>
#define maxn 110

using namespace std;
struct node {
    int data;
    int next;
}link[maxn];

int main() {
    int n, first, id;
    scanf("%d %d", &n, &first);

    for (int i = 0; i < n; i++) {
        scanf("%d", &id);
        scanf("%d %d", &link[id].data, &link[id].next);
    }

    int p = link[first].next, q = first;
    while (p != -1) {
        link[q].next = link[p].next;
        link[p].next = first;
        first = p;
        p = link[q].next;
    }

    p = first;
    while (p != -1) {
        printf("%d %d %d\n", p, link[p].data, link[p].next);
        p = link[p].next;
    }

}

两个指针p,q,p指当前待处理的结点,q指当前已经反过来的序列的尾巴,采用头插法。
1234->2134->3214->4321

K个一组倒转链表

  • 设置temp_head,temp_tail指针维护每一组首尾,注意不要让组间断开,组内就用倒转链表的算法√

环形链表

环形链表

  • 快慢指针
  • unordered_set

环形链表Ⅱ

  • unordered_set:可以很简单返回环的起始结点,但空间复杂度为O(n)
  • 快慢指针:一点点数学推理,两次相遇

链表排序🥲

合并两个有序链表

合并两个有序链表

  • 迭代写法
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode *prehead = new ListNode(-1);
        // temp指前一个已经确定顺序结点的地址
        ListNode *temp = prehead, *temp1 = list1, *temp2 = list2;

        while (temp1 != NULL && temp2 != NULL) {
            if (temp1 -> val < temp2 -> val) {
                temp -> next = temp1;
                temp1 = temp1 -> next;
            } else {
                temp -> next = temp2;
                temp2 = temp2 -> next;
            }

            temp = temp -> next;
        }

		// 处理还没处理完的
        if (temp1 != NULL) temp -> next = temp1;
        if (temp2 != NULL) temp -> next = temp2;

        return prehead -> next;
    }
};
  • 递归写法

排序链表🥲

排序链表

  • 自顶向下归并排序
    递归写法,空间:O(logn)
    sortList进行分块(快慢指针)
    merge进行合并(合并两个有序链表)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        return sortList(head, NULL);
    }

    ListNode* sortList(ListNode* head, ListNode* tail) {
        // head指头,tail指最后一个结点之后
        if (head == NULL) return head; // 空结点
        if (head -> next == tail) { // 一个结点,把结点解开,直接返回
            head -> next = NULL;
            return head;
        }
        ListNode *p = head, *q = head;

        while (p != tail && p -> next != tail) {
            p = p -> next -> next;
            q = q -> next;
        }

        head = sortList(head, q);
        q = sortList(q, tail);
        head = merge(head, q);
        
        return head;
    }

    ListNode* merge(ListNode* head1, ListNode* head2) {
        ListNode *prehead = new ListNode(-1);
        // temp1, temp2指向当前比较结点,temp指向“前一个被确定了的结点”
        ListNode *temp = prehead, *temp1 = head1, *temp2 = head2;

        while (temp1 != NULL && temp2 != NULL) {
            if (temp1 -> val < temp2 -> val) {
                temp -> next = temp1;
                temp1 = temp1 -> next;
            } else {
                temp -> next = temp2;
                temp2 = temp2 -> next;
            }

            temp = temp -> next;
        }

        if (temp1 != NULL) temp -> next = temp1;

        if (temp2 != NULL) temp -> next = temp2;

        return prehead -> next;
    }
};
  • 自底向上
    空间:O(1)

合并K个升序链表🥲

合并K个升序链表

  • 归并
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return mergeKLists(lists, 0, lists.size());
    }

    ListNode* mergeKLists(vector<ListNode*>& lists, int left, int right) {
        if (left == right) return NULL;
        if (left == right - 1) return lists[left];

        int mid = (left + right) / 2;
        ListNode *leftLists, *rightLists;
        leftLists = mergeKLists(lists, left, mid);
        rightLists = mergeKLists(lists, mid, right);

        return merge(leftLists, rightLists);
    }

    ListNode* merge(ListNode* list1, ListNode* list2) {
        ListNode *prehead = new ListNode(-1);
        ListNode *temp = prehead;

        while (list1 != NULL && list2 != NULL) {
            if (list1 -> val < list2 -> val) {
                temp -> next = list1;
                list1 = list1 -> next;
            } else {
                temp -> next = list2;
                list2 = list2 -> next;
            }

            temp = temp -> next;
        }

        if (list1 != NULL) temp -> next = list1;
        if (list2 != NULL) temp -> next = list2;

        return prehead -> next;
    }
};

两个链表相加

两数相加

删除链表倒数第N个结点

删除链表结点

  • 在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的next指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。
  • 方法一:快慢指针
  • 方法二:栈

两两交换链表结点

两两交换

  • 迭代:三个指针,创建头节点
  • 递归

复制链表

复制链表

  • unordered_map+回溯/迭代
  • 节点拆分

LRU缓存

  • 哈希+双向链表
  • 双向链表最好设置空的头节点和尾节点,统一操作
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值