LeetCode 0707.设计链表【Go】

简介: LeetCode 0707.设计链表【Go】

设计链表

LeetCode0707. 设计链表

题目描述

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

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

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

示例:

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

思路

题目要求

  • 创建一个链表类,类中有构造器和五个方法:
  • 获取链表第index个节点的数值
  • 在链表的最前面插入一个节点
  • 在链表的最后面插入一个节点
  • 在链表第index个节点前面插入一个节点
  • 删除链表的第index个节点

本题可采用单链表和双链表两种方式

单链表是最简单的一种,它提供了在常数时间内的 addAtHead 操作和在线性时间内的 addAtTail 的操作。

双链表是最常用的一种,因为它提供了在常数时间内的 addAtHeadaddAtTail 操作,并且优化了插入和删除。

双链表比单链表快得多,测试用例花费的时间比单链表快了两倍。但是它更加复杂,它包含了 size,记录链表元素个数,不计伪头伪尾。

为了使插入和删除时间消耗更少,我使用双链表;为了简化插入和删除,我在头节点前加入一个伪头。

注意

  • Go 语言中没有类(Class)的概念,但可以使用结构体(Structs)对属性进行封装,结构体就像是类的一种简化形式
  • Go 方法是作用在接收者(Receiver)上的一个函数,接收者是某种类型的变量。因此方法是一种特殊类型的函数。
    定义方法的格式如下:
func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }
  • Go语言中没有提供构造函数相关的特殊机制,用户根据自己的需求,将参数使用函数传递到结构体构造参数中即可完成构造函数的任务。
  • index0开始
  • 在添加节点后size++,删除节点后size--

代码

Go

// MyLinkedList 双链表(类)
type MyLinkedList struct {
  size      int
  dummyHead *Node
  dummyTail *Node
}
// Node 节点(结构体)
type Node struct {
  value int
  pre   *Node
  next  *Node
}
// Constructor 构造方法
func Constructor() MyLinkedList {
  dummyHead := new(Node)
  dummyTail := new(Node)
  dummyHead.next = dummyTail
  dummyTail.pre = dummyHead
  return MyLinkedList{0, dummyHead, dummyTail}
}
// GetNode 获取链表index号节点
func (this *MyLinkedList) GetNode(index int) *Node {
  p := this.dummyHead.next
  if index <= (this.size >> 1) {
    // 从前遍历
    for i := 0; i < index; i++ {
      p = p.next
    }
  } else {
    // 从后遍历
    p = this.dummyTail.pre
    for i := 0; i < this.size-1-index; i++ {
      p = p.pre
    }
  }
  return p
}
// Get 获取链表index号节点的数值
func (this *MyLinkedList) Get(index int) int {
  if index < 0 || index >= this.size {
    // 索引无效
    return -1
  }
  return this.GetNode(index).value
}
// AddAtHead 在链表的最前面插入一个节点
func (this *MyLinkedList) AddAtHead(val int) {
  head := new(Node)
  head.value = val
  head.pre = this.dummyHead
  head.next = this.dummyHead.next
  this.dummyHead.next = head
  head.next.pre = head
  this.size++
}
// AddAtTail 在链表的最后面插入一个节点
func (this *MyLinkedList) AddAtTail(val int) {
  tail := new(Node)
  tail.value = val
  tail.pre = this.dummyTail.pre
  tail.next = this.dummyTail
  this.dummyTail.pre = tail
  tail.pre.next = tail
  this.size++
}
// AddAtIndex 在链表index号节点前面插入一个节点
func (this *MyLinkedList) AddAtIndex(index int, val int) {
  if index < 0 {
    // 在链表的最前面插入一个节点
    this.AddAtHead(val)
    return
  }
  if index == this.size {
    this.AddAtTail(val)
    return
  }
  if index > this.size {
    return
  }
  indexNode := this.GetNode(index)
  newNode := new(Node)
  newNode.value = val
  newNode.pre = indexNode.pre
  newNode.next = indexNode
  indexNode.pre = newNode
  newNode.pre.next = newNode
    this.size++
}
func (this *MyLinkedList) DeleteAtIndex(index int) {
  if index < 0 || index >= this.size {
    // 索引无效
    return
  }
  indexNode := this.GetNode(index)
  indexNode.pre.next = indexNode.next
  indexNode.next.pre = indexNode.pre
    this.size--
}

Link

GitHub

目录
相关文章
|
1月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
35 1
|
1月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
48 0
Leetcode第21题(合并两个有序链表)
|
1月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
18 0
LeetCode第二十四题(两两交换链表中的节点)
|
1月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
44 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
1月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
78 0
|
1月前
【LeetCode 10】142. 环形链表 II
【LeetCode 10】142. 环形链表 II
21 0
|
1月前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
17 0
|
1月前
【LeetCode 08】206 反转链表
【LeetCode 08】206 反转链表
12 0
|
1月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
29 0
|
3月前
|
C++ 索引
leetcode 707.设计链表
本文提供了解决LeetCode 707题"设计链表"的C++实现,包括单链表的节点定义和类方法实现,如添加节点、获取节点值、删除节点等。
下一篇
无影云桌面