当前位置: 首页 > news >正文

leetcode hot100 链表(二)

书接上回:

leetcode hot100 链表(一)-CSDN博客

8.删除链表的倒数第N个结点

class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* curr=head;int len=0;while(curr){curr=curr->next;len++;}int pos=len-n;if(pos==0){ListNode* newHead=head->next;return newHead;}curr=head;while(--pos) curr=curr->next;  //目标是把curr移动到要删除结点的前面curr->next=curr->next->next;return head;}
};

9.两两交换链表中的结点

        参考leetcode灵神题解:

class Solution {
public:ListNode* swapPairs(ListNode* head) {ListNode* dummy=new ListNode(0,head); //dummy->val=0&&dummy->next=head;ListNode* node0=dummy;ListNode* node1=head;while(node1&&node1->next){ListNode* node2=node1->next;ListNode* node3=node2->next;node0->next=node2;node2->next=node1;node1->next=node3;node0=node1;node1=node3;}return dummy->next;}
};

10.k个一组反转链表

        和上题使用了相同的命名体系。

class Solution {
public:ListNode* reverseKGroup(ListNode* head, int k) {ListNode* dummy=new ListNode(0,head);ListNode* node0=dummy;ListNode* node1=node0->next;while(node1&&node1->next){ListNode* node2=node1->next;ListNode* cnt=node2;for(int i=1;i<k;i++){if(cnt==nullptr) return dummy->next;cnt=cnt->next;}for(int i=1;i<k;i++){node1->next=node2->next;node2->next=node0->next;  //node0->next始终指向当前链表的头部node0->next=node2;node2=node1->next;}node0=node1;node1=node0->next;}return dummy->next;}
};

11.随机链表的复制

        哈希映射法建立新链表结点与原节点的映射关系。

class Solution {
public:unordered_map<Node*,Node*> map;  //存储原链表节点到新链表节点的映射Node* copyRandomList(Node* head) {if(!head) return nullptr;//检查当前节点是否已经在哈希表中(即是否已经被复制过)//如果节点未被复制过,则创建一个新节点,值与原节点相同,并将原节点和新节点的映射存入哈希表if(!map.count(head)){Node* newHead=new Node(head->val);map[head]=newHead;//递归复制next指针指向的链表部分和random指针指向的节点newHead->next=copyRandomList(head->next);newHead->random=copyRandomList(head->random);}return map[head];  //返回头结点在新链表中的映射}
};

12.排序链表

        类似归并排序方法,先二分找到中点(通过快慢指针法),再对左右两边分别排序,最后合并两部分。

class Solution {// 链表的中间结点(快慢指针)ListNode* middleNode(ListNode* head) {ListNode* pre=head;ListNode* slow=head;ListNode* fast=head;while (fast&&fast->next) {pre=slow; // 记录 slow 的前一个节点slow=slow->next;fast=fast->next->next;}pre->next=nullptr; // 断开 slow 的前一个节点和 slow 的连接return slow;  // 链表后半部分}// 合并两个有序链表(双指针),归并思想ListNode* merge(ListNode* list1, ListNode* list2) {ListNode dummy; // 用哨兵节点简化代码逻辑ListNode* cur=&dummy; // cur 指向新链表的末尾while(list1&&list2){if(list1->val<=list2->val){cur->next=list1; // 把 list1 加到新链表中list1=list1->next;} else{ cur->next=list2;list2=list2->next;}cur=cur->next;}cur->next=list1?list1:list2; // 拼接剩余链表return dummy.next;}
public:ListNode* sortList(ListNode* head) {if (!head||!head->next) return head;// 找到中间节点 head2,并断开 head2 与其前一个节点的连接,然后分治、合并// 比如 head=[4,2,1,3],那么 middleNode 调用结束后 head=[4,2] head2=[1,3]ListNode* head2 = middleNode(head);head=sortList(head);head2=sortList(head2);return merge(head, head2);}
};

13.合并k个升序链表

        利用小根堆实现,小根堆里维护每个非空链表未被处理的第一个结点

class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) {struct Cmp{bool operator()(ListNode* a, ListNode* b){return a->val>b->val;}};priority_queue<ListNode*,vector<ListNode*>,Cmp> min_heap;  //优先队列模拟小根堆for(ListNode* node:lists){if (node) min_heap.push(node);  //把所有非空链表的头结点入堆 }ListNode dummy(0);  ListNode* tail=&dummy;  //tail负责维护合并后的新链表while(!min_heap.empty()){ListNode* min_node=min_heap.top();  //剩余结点中的最小结点min_heap.pop(); if(min_node->next) min_heap.push(min_node->next);tail->next=min_node;  //把min_node添加到新链表末尾tail=tail->next;  //准备合并下一个结点}return dummy.next;}
};

14.LRU缓存

struct DLinkedNode {int key, value;DLinkedNode* prev;DLinkedNode* next;DLinkedNode():key(0),value(0),prev(nullptr),next(nullptr){}DLinkedNode(int _key,int _value):key(_key),value(_value),prev(nullptr),next(nullptr){}
};
class LRUCache {
private:unordered_map<int, DLinkedNode*> cache;DLinkedNode* head;DLinkedNode* tail;int size;int capacity;
public:LRUCache(int _capacity): capacity(_capacity), size(0) {// 使用伪头部和伪尾部节点head = new DLinkedNode();tail = new DLinkedNode();head->next=tail;tail->prev=head;}int get(int key){if(!cache.count(key)) return -1;// 如果 key 存在,先通过哈希表定位,再移到头部DLinkedNode* node=cache[key];moveToHead(node);return node->value;}void put(int key, int value) {if (!cache.count(key)) {// 如果 key 不存在,创建一个新的节点DLinkedNode* node = new DLinkedNode(key, value);// 添加进哈希表cache[key] = node;// 添加至双向链表的头部addToHead(node);size++;if(size>capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode* removed = removeTail();// 删除哈希表中对应的项cache.erase(removed->key);// 防止内存泄漏delete removed;size--;}}else {// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部DLinkedNode* node = cache[key];node->value = value;moveToHead(node);}}void addToHead(DLinkedNode* node) {node->prev=head;node->next=head->next;head->next->prev=node;head->next=node;}void removeNode(DLinkedNode* node) {node->prev->next=node->next;node->next->prev=node->prev;}void moveToHead(DLinkedNode* node){removeNode(node);addToHead(node);}DLinkedNode* removeTail(){DLinkedNode* node=tail->prev;removeNode(node);return node;}
};

相关文章:

  • Spring Boot + MyBatis-Plus 读写分离与多 Slave 负载均衡示例
  • 适老化场景重构:现代家政老年照护虚拟仿真实训室建设方案​
  • 如何在 vue 中实现一个自定义拖拽的指令或插件
  • qt 事件顺序
  • Laravel模型状态:深入理解Eloquent的隐秘力量
  • QT常用控件(1)
  • metersphere不同域名的参数在链路测试中如何传递?
  • 项目任务,修改svip用户的存储空间。
  • 微博app 最新版本15.5.2 mfp 分析
  • RagFlow优化代码解析(一)
  • 操作系统:生态思政
  • 现代密码学 | 椭圆曲线密码学—附py代码
  • 如何从系统日志中排查磁盘错误?
  • 0518蚂蚁暑期实习上机考试题1:数组操作
  • “轻量应用服务器” vs. “云服务器CVM”:小白入门腾讯云,哪款“云机”更适合你?(场景、配置、价格对比解析)
  • 神经符号集成-三篇综述
  • Docker 镜像(或 Docker 容器)中查找文件命令
  • 2023-2025 时序大模型相关工作汇总
  • 生产环境中安装和配置 Nginx 以部署 Flask 应用的详细指南
  • 架构设计的目标:高内聚、低耦合的本质
  • 华为云做网站不能修改页面/网络营销方法有哪些?
  • 网页制作与设计课程设计报告/优化大师下载
  • 网站开发如何压缩图片/无锡网站推广公司
  • 企业做网站哪个最好/seo教程优化
  • 网站排名优化原理/seo关键词推广怎么做
  • 做网站年赚千万/典型的网络营销案例