爱写bug (ID:iCodeBugs)

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:valnextval 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

Design your implementation of the linked list. You can choose to use the singly linked list or the doubly linked list. A node in a singly linked list should have two attributes: val and next. val is the value of the current node, and next is a pointer/reference to the next node. If you want to use the doubly linked list, you will need one more attribute prev to indicate the previous node in the linked list. Assume all nodes in the linked list are 0-indexed.

Implement these functions in your linked list class:

  • get(index) : Get the value of the index-th node in the linked list. If the index is invalid, return -1.
  • addAtHead(val) : Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
  • addAtTail(val) : Append a node of value val to the last element of the linked list.
  • addAtIndex(index, val) : Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
  • deleteAtIndex(index) : Delete the index-th node in the linked list, if the index is valid.

示例:

MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3
linkedList.get(1); //返回2
linkedList.deleteAtIndex(1); //现在链表是1-> 3
linkedList.get(1); //返回3

提示:

  • 所有值都在 [1, 1000] 之内。
  • 操作次数将在 [1, 1000] 之内。
  • 请不要使用内置的 LinkedList 库。

解题思路:

先看图解:

  • 单链表添加操作

如果我们想在给定的结点 prev 之后添加新值,我们应该:

  1. 使用给定值初始化新结点 cur;
  2. cur 的“next”字段链接到 prev 的下一个结点 next
  3. prev 中的“next”字段链接到 cur
  • 删除第一个结点

如果我们想删除第一个结点,策略会有所不同。

正如之前所提到的,我们使用头结点 head 来表示链表。我们的头是下面示例中的黑色结点 23。

如果想要删除第一个结点,我们可以简单地将下一个结点分配给 head。也就是说,删除之后我们的头将会是结点 6。

链表从头结点开始,因此结点 23 不再在我们的链表中。

图片来源于LeetCode中国官网

高级程序设计语言中一般都有内置链表,这道题就是让复现链表,看到有很多是用ArrayList、List等数据结构解的,很搞笑,题目说不能使用 LinkedList 库,但 LinkedList 是继承的ArrayList、List,,直接用这两个库一点意义都没有。其实理解一下链表原理就好,高级语言都封装好了链表,如果项目真的到了需要改写链表底层结构来优化性能的那一步,那时候在实践中基本已经摸清了这些东西。

Java:

class Node {//定义Node
int val;
Node next; Node(int val) {
this.val = val;
this.next = null;
}
} class MyLinkedList { Node head;//头
Node tail;//尾
int size = 0;//链表长度 public MyLinkedList() {//初始化数据
head = new Node(0);//为了方便初始化一个本不存在的head,值为0
tail = head;//初始下尾也指向和头同一个对象
size = 0;
} public int get(int index) {
if (index >= size || index < 0) {//index不在查找区间返回-1
return -1;
}
Node cur = head;
for (int i = 0; i <= index; i++) {//从head一个一个向下遍历,到index
cur = cur.next;
}
return cur.val;//返回值
} public void addAtHead(int val) {
Node temp = head.next;//temp对象是真实链表的第一个节点(因为head一直是初始化的 0 )
head.next = new Node(val);//构造的虚拟节点head的下一个节点指向新插入的节点
head.next.next = temp;//新插入节点指向原本第一个真实节点
size++;//计数
if (size == 1) {
tail = head.next;//如果只有一个节点此时尾节点也指向新加入的节点
}
} public void addAtTail(int val) {//添加尾节点
tail.next = new Node(val);//把尾节点下一个对象指向新加入节点即可
tail = tail.next;//刷新尾节点为新加入的节点
size++;
} public void addAtIndex(int index, int val) {
if (index > size) {//插入值不在范围直接返回。
return;
}
Node cur = head;//当前节点从头节点开始
for (int i = 0; i < index; i++) {//遍历到 插入位置的前一个节点 因为要求是插入到index的前面
cur = cur.next;
}
Node temp = cur.next;//暂存当前节点的下一个节点
cur.next = new Node(val);//把当前节点下一个对象指向新节点
if (index == size) {
tail = cur.next;//如果插入位置刚好是最后一个则把尾节点指向新加入节点
}
cur.next.next = temp;//新节点的下一个节点指向暂存节点位置
size++;
} public void deleteAtIndex(int index) {
if (index >= size || index < 0) {
return;
}
Node cur = head;//从头节点遍历到index目标节点的前一个节点 因为要删除目标节点
for (int i = 0; i < index; i++) {
cur = cur.next;
} cur.next = cur.next.next;//目标节点前一个节点的下一个节点指向目标节点的下一个节点
size--;//刷新节点数量
if (cur.next == null) {
tail = cur;
}
}
}

Python3:

class Node:
def __init__(self, val, _next=None):
self.next = _next
self.val = val class MyLinkedList:
def __init__(self):
self.head = None
self.tail = None
self.size = 0 def get(self, index: int) -> int:
if index > self.size - 1 or index < 0:
return -1
node = self.head
for i in range(index):
node = node.next
return node.val def addAtHead(self, val: int) -> None:
node = Node(val, self.head)
self.head = node
if self.size == 0:
self.tail = node
self.size = self.size + 1 def addAtTail(self, val: int) -> None:
node = Node(val)
if self.size == 0:
self.head = self.tail = node # 原链表为空时,添加新节点后,更新链表的头指针和尾指针为新增节点。
else:
self.tail.next = node # 原链表不为空时,使原尾指针指向新节点,即可将新节点添加至原链表尾部
self.tail = node # 更新尾指针
self.size = self.size + 1 # 更新此时链表的长度 def addAtIndex(self, index: int, val: int) -> None:
node = Node(val)
if index > self.size:
return
if index <= 0:
return self.addAtHead(val) # index 小于等于0都默认为头指针后添加节点 if index == self.size: # 如果index等于链表的长度添加尾指针后添加节点
return self.addAtTail(val)
prev = self.head # 第一个节点对象开始遍历
for i in range(index - 1):
prev = prev.next
temp = prev.next
prev.next = node
node.next = temp
self.size = self.size + 1 def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size:
return
prev = self.head
if index == 0:
self.head = self.head.next
self.size = self.size - 1
return
for i in range(index - 1):
prev = prev.next
if index == self.size - 1:
self.tail = prev
prev.next = prev.next.next
self.size = self.size - 1

公众号:爱写bug (ID:iCodeBugs)

LeetCode707:设计链表 Design Linked List的更多相关文章

  1. [Swift]LeetCode707. 设计链表 | Design Linked List

    Design your implementation of the linked list. You can choose to use the singly linked list or the d ...

  2. LeetCode707 设计链表

    设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的值,next 是指向下一个节点的指针/引用.如果要使用双向链表,则还需要一个属性 ...

  3. Leetcode707.Design Linked List设计链表

    设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的值,next 是指向下一个节点的指针/引用.如果要使用双向链表,则还需要一个属性 ...

  4. 【LeetCode】Design Linked List(设计链表)

    这道题是LeetCode里的第707到题.这是在学习链表时碰见的. 题目要求: 设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的 ...

  5. C#LeetCode刷题之#707-设计链表(Design Linked List)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4118 访问. 设计链表的实现.您可以选择使用单链表或双链表.单链 ...

  6. 707. Design Linked List

    1. 原始题目 Design your implementation of the linked list. You can choose to use the singly linked list ...

  7. 【LeetCode】设计题 design(共38题)

    链接:https://leetcode.com/tag/design/ [146]LRU Cache [155]Min Stack [170]Two Sum III - Data structure ...

  8. LeetCode | 707. 设计链表

    设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的值,next 是指向下一个节点的指针/引用.如果要使用双向链表,则还需要一个属性 ...

  9. 异或链表(XOR linked list)

    异或链表(Xor Linked List)也是一种链式存储结构,它可以降低空间复杂度达到和双向链表一样目的,任何一个节点可以方便的访问它的前驱节点和后继结点.可以参阅wiki 普通的双向链表 clas ...

随机推荐

  1. 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 7

    23.5  创建RESTful规范 WebAPI框架 虽然我们现在可以自己实现API了,也了解了RESTful API的设计原则,但让自己实现的API符合RESTful API规范,对很多刚接触API ...

  2. IT兄弟连 Java语法教程 流程控制语句 控制循环结构1

    Java语言没有提供goto语句来控制程序的跳转,这种做法提高了程序流程控制的可读性,但降低了程序流程控制的灵活性.为了弥补这种不足,Java提供了continue和break来控制循环结构.除此之外 ...

  3. 基于 EntityFramework 生成 Repository 模式代码

    借助 WeihanLi.EntityFramework 实现简单的 Repository Intro 很多时候一些简单的业务都是简单的增删改查,动态生成一些代码完成基本的增删改查,而这些增删改查代码大 ...

  4. GO 数组

    一.数组(Array) 1.1 什么是数组 Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定义类型. ...

  5. java高并发系列 - 第10天:线程安全和synchronized关键字

    这是并发系列第10篇文章. 什么是线程安全? 当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出正常的行为(与自己预想的结果一致),那我们就可以所这个类是线程安全的. 看一段代码: pack ...

  6. Java生鲜电商平台-Java后端生成Token架构与设计详解

    Java生鲜电商平台-Java后端生成Token架构与设计详解 目的:Java开源生鲜电商平台-Java后端生成Token目的是为了用于校验客户端,防止重复提交. 技术选型:用开源的JWT架构. 1. ...

  7. HTML5新标签与特性---多媒体

    多媒体标签 embed:标签定义嵌入的内容 audio:播放音频 video:播放视频 多媒体 embed(会使用) embed可以用来插入各种多媒体,格式可以是 Midi.Wav.AIFF.AU.M ...

  8. 前端开发工具HBuilder使用技巧以及快捷键

    创建HTML结构: h 8 (敲h激活代码块列表,按8选择第8个项目,即HTML代码块,或者敲h t Enter) 中途换行: 'Ctrl+Enter' 设置charset: m e 6 Enter ...

  9. iOS10跳转至设置页面

    在iOS10之前,跳转到系统设置界面的某个指定界面的方式如下: //打开定位服务界面 NSURL*url=[NSURL URLWithString:@"prefs:root=Privacy& ...

  10. XCode保存问题

    1. 确认下证书是不是开发证书,如果是发布证书就会出现这样的提示. 2. 证书失效了,去开发者中心重新生成一个. 3. 包标识符不与描述文件包含的包标识符不一致,按照它的提示换一下就好了,最好不要点 ...