前言
今天写题也是开始比较晚,写了一道题,中等难度的设计链表题目,对golang结构体也是通过这道题熟悉了一下。
内容
设计链表
707,设计链表 (中等题,覆盖链表知识较多,必须吃透)
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val
和 next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 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
的节点。
提示:
0 <= index, val <= 1000
- 请不要使用内置的 LinkedList 库。
- 调用
get
、addAtHead
、addAtTail
、addAtIndex
和deleteAtIndex
的次数不超过2000
单链表
设计题本身其实原理是很简单的,也不涉及算法。 但是很容易错。(题解看到的)
//24ms 6.67MB
type MyLinkedList struct {
head *ListNode
size int
}
// type ListNode struct {
// Val int // 节点的值
// Next *ListNode // 下一个节点的指针
// }
//这个是内置的不用写
//MyLinkedList 是一个结构,包含一个指向链表头的指针 head 和一个记录链表大小的整数 size
func Constructor() MyLinkedList {
return MyLinkedList{&ListNode{},0}
}
//这是一个构造函数,用于创建 MyLinkedList 的实例。它初始化一个空链表,头结点为 &ListNode{}(一个空链表结点),链表大小为 0。
func (this *MyLinkedList) Get(index int) int {
if index<0||index>=this.size{
return -1
}
cur:=this.head
for i:=0;i<=index;i++{
cur=cur.Next
}
return cur.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>this.size{
return
}
//确保 index 不会小于 0,因为数组或链表索引不能为负数。如果 index 是负数,那么它会变成 0。如果 index 是正数或 0,那么它保持不变。
index=max(0,index)
this.size++
dummy:=this.head
for i:=0;i<index;i++{
dummy=dummy.Next
}
toAdd:=&ListNode{val,dummy.Next}//这行代码创建了一个新的链表节点。这个节点的值是val,它的下一个节点是指向dummy.Next的节点。这里,pred是当前节点,dummy.Next是当前节点的下一个节点。所以,&ListNode{val, dummy.Next}创建了一个新的节点,并将这个新节点的地址赋值给toAdd。
dummy.Next=toAdd
//这行代码将新的节点添加到链表中。具体来说,它将dummy节点的下一个节点设置为toAdd指向的节点,也就是新创建的节点。这样,新创建的节点就被添加到了链表的指定位置
}
func (this *MyLinkedList) DeleteAtIndex(index int) {
if index<0||index>=this.size{
return
}
this.size--
dummy:=this.head
for i:=0;i<index;i++{
dummy=dummy.Next
}
dummy.Next=dummy.Next.Next
}
func max(a, b int) int {
if b > a {
return b
}
return a
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Get(index);
* obj.AddAtHead(val);
* obj.AddAtTail(val);
* obj.AddAtIndex(index,val);
* obj.DeleteAtIndex(index);
*/
双链表
单链表是内置的,双向链表得自己定义 24ms 6.69MB
type node struct{
val int
next,prev *node
}
type MyLinkedList struct {
head,tail *node
size int
}
// 构造函数
func Constructor() MyLinkedList {
head:=&node{}
tail:=&node{}
head.next=tail
tail.prev=head
return MyLinkedList{head,tail,0}
}
func (this *MyLinkedList) Get(index int) int {
if index < 0 || index >= this.size {
return -1
}
var cur *node
if index+1<this.size-index{
cur=this.head
for i:=0;i<=index;i++{
cur=cur.next
}
}else{
cur=this.tail
for i:=0;i<this.size-index;i++{
cur=cur.prev
}
}
return cur.val
//index+1 代表当我们从头部开始遍历时,到达目标索引需要经过的节点数。例如,如果 index 是0,那么我们需要经过1个节点到达目标索引。
//l.size-index 代表当我们从尾部开始遍历时,到达目标索引需要经过的节点数。例如,如果 index 是0,那么我们需要经过 l.size-0 个节点到达目标索引。
}
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 > this.size {
return
}
index=max(0,index)
//双向链表 添加一个新结点 要有prev和next
var pred,succ *node
if index<this.size-index{
pred=this.head
for i := 0; i < index; i++ {
pred = pred.next
}
succ=pred.next
}else{
succ=this.tail
for i:=0;i<this.size-index;i++{
succ=succ.prev
}
pred=succ.prev
}
this.size++
toAdd := &node{val, succ,pred}
pred.next = toAdd
succ.prev=toAdd
}
func (this *MyLinkedList) DeleteAtIndex(index int) {
if index < 0 || index >= this.size {
return
}
//要删除结点的前驱节点和后继结点
var pred,succ *node
if index<this.size-index{
pred=this.head
for i := 0; i < index; i++ {
pred=pred.next
}
succ = pred.next.next
}else{
succ=this.tail
for i:=0;i<this.size-index-1;i++{
succ=succ.prev
}
pred=succ.prev.prev
}
this.size--
pred.next=succ
succ.prev=pred
}
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}
最后
很多事都没有完成,太焦虑了,心态不稳。。。