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

设计双向链表--LeetCode

题目

设计双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。

实现 MyLinkedList 类:

  • MyLinkedList() 初始化 MyLinkedList 对象。
  • int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
  • void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
  • void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
  • void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
  • void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。

思路

实现双向链表,即每个节点要存储本身的值,后继节点和前驱节点。除此之外,需要一个哨兵节点作为头节点 head 和一个哨兵节点作为尾节点 tail。仍需要一个 size 参数保存有效节点数。如下图所示。

img

初始化时,只需创建头节点 head 和 size 即可。

实现 get(index) 时,先判断有效性,然后再比较从 head 还是 tail 来遍历会比较快找到目标,然后进行遍历。如下图所示。

img


实现 addAtIndex(index, val) 时,如果 index 是有效值,则需要找到原来下标为 index 的节点 succ 和前驱节点 pred,并创建新节点 to_add,再通过各自 prev 和 next 变量的更新来增加to_add。最后需要更新 size。如以下两张图所示。

img

实现 addAtHead(val) 和 addAtTail(val) 时,可以借助 addAtIndex(index, val) 来实现。

实现 deleteAtIndex(index),先判断参数有效性。然后找到下标为 index 的节点的前驱节点 pred 和后继节点 succ,再通过各自 prev 和 next 变量的更新来删除节点,来达到删除节点的效果。同时也要更新 size。如下图所示。

img

class MyLinkedList {//双向链表int size;ListNode head;//虚拟头结点ListNode tail;//虚拟尾结点public MyLinkedList() {size = 0;head = new ListNode(0);tail = new ListNode(0);head.next = tail;//中间节点为空tail.prev = head;}public int get(int index) {if (index < 0 || index >= size) {return -1;}ListNode curr;//判断查询的位置在链表前半部分还是后半部分,节省循环if (index + 1 < size - index) {curr = head;//从头开始遍历for (int i = 0; i <= index; i++) {curr = curr.next;}} else {curr = tail;//从尾开始遍历for (int i = 0; i < size - index; i++) {curr = curr.prev;}}return curr.val;}public void addAtHead(int val) {addAtIndex(0, val);}public void addAtTail(int val) {addAtIndex(size, val);}public void addAtIndex(int index, int val) {if (index > size) {return;}index = Math.max(0, index);//插入位置负数,其插入位置在链表头ListNode pred, succ;//index前一个结点、后一个结点if (index < size - index) {pred = head;for (int i = 0; i < index; i++) {pred = pred.next;}succ = pred.next;} else {succ = tail;for (int i = 0; i < size - index; i++) {succ = succ.prev;}pred = succ.prev;}size++;ListNode toAdd = new ListNode(val);toAdd.prev = pred;toAdd.next = succ;pred.next = toAdd;succ.prev = toAdd;}public void deleteAtIndex(int index) {if (index < 0 || index >= size) {return;}ListNode pred, succ;if (index < size - index) {pred = head;for (int i = 0; i < index; i++) {pred = pred.next;}succ = pred.next.next;} else {succ = tail;for (int i = 0; i < size - index - 1; i++) {succ = succ.prev;}pred = succ.prev.prev;}size--;pred.next = succ;succ.prev = pred;}
}class ListNode {int val;ListNode next;//指向下一个结点指针ListNode prev;//指向前一个结点指针public ListNode(int val) {this.val = val;}
}

相关文章:

  • MinerU教程第二弹丨MinerU 本地部署保姆级“喂饭”教程
  • BGE-M3 文本情感分类实战:预训练模型微调,导出ONNX并测试
  • OpenCv高阶(十七)——dlib库安装、dlib人脸检测
  • Jeecg漏洞总结及tscan poc分享
  • Mujoco 学习系列(四)官方模型仓库 mujoco_menagerie
  • LangChain文档加载器实战:构建高效RAG数据流水线
  • 第八天的尝试
  • js中encodeURIComponent函数使用场景
  • 3.9/Q1,GBD数据库最新文章解读
  • FinalShell 密码在线解析方法(含完整源码与运行平台)
  • SQLServer与MySQL数据迁移案例解析
  • mysql日志文件binlog分析记录
  • 软考 系统架构设计师系列知识点之杂项集萃(69)
  • [Usaco2007 Dec]队列变换 题解
  • Python之web错误处理与异常捕获
  • LeRobot的机器人控制系统(下)
  • 有监督学习——决策树
  • 从3.7V/5V到7.4V,FP6291在应急供电智能门锁中的应用
  • 为什么mosquitto 禁用了 topic “#“后,无法使用主题中包含%c client_id了?
  • 【动手学深度学习】2.1. 数据操作
  • 如何做cad的模板下载网站/百度指数功能模块有哪些
  • 网页设计图片显示不出来/广州百度seo排名
  • wordpress 响应式 主题/西安优化seo托管
  • 郑州工装定制/进行优化
  • 昌平网站设计/镇江百度公司
  • 网站建设淄博佳铉网络/泰安网络推广培训