力扣刷题第九天--链表篇

前言

今天写题也是开始比较晚,写了一道题,中等难度的设计链表题目,对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 库。
  • 调用 getaddAtHeadaddAtTailaddAtIndex 和 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
	}
}

最后

很多事都没有完成,太焦虑了,心态不稳。。。

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值