0707-leetcode算法实现之设计链表-design-linked-list-python&golang实现
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,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
提示:
所有val值都在 [1, 1000] 之内。
操作次数将在 [1, 1000] 之内。
请不要使用内置的 LinkedList 库。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/design-linked-list
python
# 0707.设计链表实现以下5中功能:
# -根据索引获取值
# -头插
# -尾插
# -根据索引插入
# -根据索引删除
# 单链表
class Node:
def __init__(self, val):
self.val = val
self.next = None
class Mylinklist:
def __init__(self, node=None):
if node != None:
# 当节点非空时,实例化节点,让头结点指向节点
headNode = Node(node)
self._head = headNode
else:
# 如果节点空,头结点指向None
self._head = node
def length(self):
"""
初始化计数,当节点非空,不断右移,计数器++,重复,返回计数
:return:
"""
cnt = 0
cur = self._head
while cur:
cur = cur.next
cnt += 1
return cnt
def transverse(self):
"""
当前节点即为头结点,非空即打印节点值,指针右移,重复
:return:
"""
cur = self._head
while cur:
print(cur.val)
cur = cur.next
def get(self, index: int) -> int:
"""
初始化计数器,初始化从头结点开始,遍历节点,
如果遍历到计数器等于index,即找到合适index的值返回,
否则计数器++,链表指针右移,重复
如果遍历链表没有index,即返回-1,表示index超出了链表范围
:param index:
:return:
"""
cnt = 0
cur =self._head
while cur:
if cnt == index:
return cur.val
cnt += 1
cur = cur.next
return -1
def addAtHead(self, val) -> None:
"""
头部插入节点,根据节点值,生成节点对象,让该节点指向头结点,头结点指向node
:param val:
:return:
"""
node = Node(val)
node.next = self._head # 代表节点指向头结点的next对象
self._head = node
def addAtTail(self, val: int) -> None:
node = Node(val)
# 尾部插入判断当前链表是否空
# 空链表时,头部指向为空,直接让头部指向节点
if self._head == None:
self._head = Node
# 一般情况下,遍历到尾部,尾部节点指向插入节点,插入节点指向None
else:
cur = self._head
# 遍历到最后一个节点时,next为None,即break循环
while cur.next != None:
cur = cur.next
# 尾部节点指向插入节点,完成尾部插入
cur.next = node
def addAtIndex(self, index: int, val: int) -> None:
"""
给定插入位置,与插入的值,需要插入位置的前序节点pre, 和当前节点cur,
pre指向node, node指向cur
:param val:
:return:
"""
node = Node(val)
# index < 0,头插
if index < 0:
self.addAtHead(val)
# index越界,尾插
elif index > self.length():
self.addAtTail(val)
# 一般情况,链表中插入
# 通过遍历计数比较index获取index-1位置节点
# 插入节点的next指针指向p先序节点的next
# 先序节点指向插入节点,完成插入,且不断
else:
cnt = 0
pre = self._head
while cnt < index:
pre = pre.next
cnt += 1
node.next = pre.next
pre.next = node
def deleteAtIndex(self, index: int) -> None:
# 给定index<0,直接返回空
if index < 0:
return
# index为0时,头部指向当前头部的next即可
elif index == 0:
self._head = self._head.next
# 一般情况下index>0, 分链表长度内的或越界的,2种情况
else:
cnt = 0
cur = self._head
while cnt < index:
cur = cur.next
cnt += 1
# 遍历结束后,index-1位置的元素的next指向其next的next
if cur.next != None:
cur.next = cur.next.next
# 否则,越界
else:
return
if __name__ == "__main__":
node = Mylinklist()
node.addAtHead(200)
print(node.get(0))
node.addAtHead(250)
node.addAtTail(260)
node.addAtIndex(2,251)
print(node.get(0))
node.transverse()
print(node.length())
node.deleteAtIndex(1)
print(node.length())
node.transverse()
---以下为官方
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class MyLinkedList:
def __init__(self):
self.size = 0
self.head = ListNode(0) # sentinel node as pseudo-head
def get(self, index: int) -> int:
"""
Get the value of the index-th node in the linked list. If the index is invalid, return -1.
"""
# if index is invalid
if index < 0 or index >= self.size:
return -1
curr = self.head
# index steps needed
# to move from sentinel node to wanted index
for _ in range(index + 1):
curr = curr.next
return curr.val
def addAtHead(self, val: int) -> None:
"""
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.
"""
self.addAtIndex(0, val)
def addAtTail(self, val: int) -> None:
"""
Append a node of value val to the last element of the linked list.
"""
self.addAtIndex(self.size, val)
def addAtIndex(self, index: int, val: int) -> None:
"""
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.
"""
# If index is greater than the length,
# the node will not be inserted.
if index > self.size:
return
# [so weird] If index is negative,
# the node will be inserted at the head of the list.
if index < 0:
index = 0
self.size += 1
# find predecessor of the node to be added
pred = self.head
for _ in range(index):
pred = pred.next
# node to be added
to_add = ListNode(val)
# insertion itself
to_add.next = pred.next
pred.next = to_add
def deleteAtIndex(self, index: int) -> None:
"""
Delete the index-th node in the linked list, if the index is valid.
"""
# if the index is invalid, do nothing
if index < 0 or index >= self.size:
return
self.size -= 1
# find predecessor of the node to be deleted
pred = self.head
for _ in range(index):
pred = pred.next
# delete pred.next
pred.next = pred.next.next
---双向链表
# 双向链表
class ListNode:
def __init__(self, val):
self.val = val
self.next, self.prev = None, None
class MyLinkerList:
def __init__(self):
self.size = 0
# 哨兵作为虚拟头尾节点
self.head, self.tail = ListNode(0), ListNode(0)
self.head.next = self.tail
self.tail.prev = self.head
def get(self, index: int) -> int:
if index < 0 or index >= self.size:
return -1
# 头部遍历
if index + 1 < self.size - index:
cur = self.head
for _ in range(index+1):
cur = cur.next
# 尾部遍历
else:
cur = self.tail
for _ in range(self.size - index):
cur = cur.prev
return cur.val
def addAtHead(self, val: int) -> None:
prev, next = self.head, self.head.next # 头部前2节点
self.size += 1 # 新增加点,长度加1
node = ListNode(val)
node.prev = prev # 插入节点前序指针指向头1节点
node.next = next # 插入节点后继指针指向原头二节点
prev.next = node # 头1节点后继指针指向节点
next.prev = node # 原头2节点的前序指针指向节点
def addAtTail(self, val: int) -> None:
# 与头插类似
next, prev = self.tail, self.tail.prev
self.size += 1
node = ListNode(val)
node.prev = prev
node.next = next
prev.next = node
next.prev = node
def addAtIndex(self, index: int, val: int) -> None:
if index > self.size:
return
if index < 0:
index = 0
if index < self.size - index: # 头部插入,向后遍历
prev = self.head
for _ in range(index):
prev = prev.next
next = prev.next
else: # 尾部插入,向前遍历
next = self.tail
for _ in range(self.size-index):
next = next.prev
prev = next.prev
self.size += 1
node = ListNode(val)
node.prev = prev
node.next = next
prev.next = node
next.prev = node
def deleteAtIndex(self, index: int) -> None:
if index < 0 or index > index.size:
return
if index < self.size - index:
prev = self.head
for _ in range(index):
prev = prev.next
next = prev.next.next
else:
next = self.tail
for _ in range(self.size-index):
next = next.prev
prev = next.prev.prev
# rm node
self.size -= 1
prev.next = next
next.prev = prev
golang
# 单链表
type ListNode struct {
Val int
Next *ListNode
}
type MyLinkedList struct {
size int
head *ListNode
}
// initialize data structure
func Constructor() MyLinkedList {
return MyLinkedList{
0,
&ListNode{},
}
}
func (this *MyLinkedList) Get(index int) int {
if index < 0 || index > this.size {
return -1
}
prev := this.head
for i := 0; i < index; i++ {
prev = prev.Next
}
return prev.Next.Val
}
func (this *MyLinkedList) AddAtHead(val int) {
this.AddAtIndex(0, val)
}
func (this *MyLinkedList) AddAtTail(val int) {
this.AddAtIndex(this.size, val)
}
func (this *MyLinkedList) AddAtIndex(index int, val int) {
if index < 0 || index > this.size {
return
}
pre := this.head
for i := 0; i < index; i++ {
pre = pre.Next
}
node := &ListNode{Val: val}
node.Next = pre.Next
pre.Next = node
this.size++
}
func (this *MyLinkedList) DeleteAtIndex(index int) {
if index < 0 || index > this.size {
return
}
prev := this.head
for i := 0; i < index; i++ {
prev = prev.Next
}
prev.Next = prev.Next.Next
this.size++
}
---以下双链表
// 定义链表节点
type Node struct {
Next *Node
Prev *Node
Val int
}
type MyLinkedList struct {
head *Node // 头结点
tail *Node // 尾结点
size int // 链表的长度
}
/** Initialize your data structure here. */
func Constructor() MyLinkedList {
return MyLinkedList{}
}
/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
func (this *MyLinkedList) Get(index int) int {
// index无效
if this.size == 0 || index < 0 || index >= this.size {
return -1
}
// index为头尾节点
if index == 0 {
return this.head.Val
}
if index == this.size-1 {
return this.tail.Val
}
// 下面选择更快的遍历方向, 查看index在偏头部还是偏尾部
cur := this.head
count := 0
for cur != nil {
if count == index {
break
}
count++
cur = cur.Next
}
return cur.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. */
func (this *MyLinkedList) AddAtHead(val int) {
node := &Node{Val: val}
if this.head != nil {
node.Next = this.head
this.head.Prev = node
this.head = node
} else {
this.head = node
this.tail = this.head
}
this.size++
}
/** Append a node of value val to the last element of the linked list. */
func (this *MyLinkedList) AddAtTail(val int) {
node := &Node{Val: val}
if this.tail != nil {
node.Prev = this.tail
this.tail.Next = node
this.tail = node
} else {
this.tail = node
this.head = this.tail
}
this.size++
}
/** 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. */
func (this *MyLinkedList) AddAtIndex(index int, val int) {
if index > this.size {
return
}
if index <= 0 {
this.AddAtHead(val)
return
}
if index == this.size {
this.AddAtTail(val)
return
}
cur := this.head
count := 0
for cur != nil && count < index {
count++
cur = cur.Next
}
// 在当前节点cur的前面插入
this.size++
node := &Node{Val: val, Next: cur, Prev: cur.Prev}
cur.Prev.Next = node
cur.Prev = node
}
/** Delete the index-th node in the linked list, if the index is valid. */
func (this *MyLinkedList) DeleteAtIndex(index int) {
// 如果索引无效 || 链表为空
if this.size == 0 || index < 0 || index >= this.size {
return
}
if index == 0 {
// 如果删除的是头结点
this.head = this.head.Next
} else if index == this.size-1 {
// 如果删除的是尾结点
this.tail = this.tail.Prev
} else {
cur := this.head
count := 0
for cur != nil && count < index {
count++
cur = cur.Next
}
// 找到要删除的节点cur了
cur.Next.Prev = cur.Prev
cur.Prev.Next = cur.Next
}
this.size--
}