Golang leetcode707 设计链表 (链表大成)

news/2025/2/23 5:12:51

文章目录

  • 设计链表 Leetcode707
    • 不使用头节点
    • 使用头节点 推荐**

设计链表 Leetcode707

题目要求我们通过实现几个方法来完成对链表的各个操作
由于在go语言中都为值传递,(注意这里与值类型、引用类型的而区别),所以即使我们直接在方法中传入指针,但是我们在方法里是不能直接修改指针所改的地址,其在方法中只会复制一份副本进行操作,而不会影响到原变量。
所以我们这里可以设置一个结构体,在mylinkedlist中在定义链表节点进行解决。
关于值传递的注意事项

这里放一个经典的愚蠢案例以作警戒,妄想通过副本直接影响原链表
我是猪

func (this *MyLinkedList) AddAtTail(val int) {
	Node := this.Head
	if Node == nil {
		Node = &ListNode{Val: val}
		//this.Head = Node
		return
	}
	for Node.Next != nil {
		Node = Node.Next
	}
	Node.Next = &ListNode{Val: val}
}

不使用头节点

// ListNode 定义链表结构
type ListNode struct {
	Val  int
	Next *ListNode
}

//正常建立,不涉及头节点
// MyLinkedList 为了方便操作链表建立的结构体
type MyLinkedList struct {
	size int
	Head *ListNode
}

// Constructor 初始化链表对象 √
func Constructor() MyLinkedList {
	return MyLinkedList{}
}

// Get 获取第index个节点的数据 √
func (this *MyLinkedList) Get(index int) int {
	if index+1 > this.size {
		return -1
	}

	Node := this.Head

	for ; index > 0; index-- {
		Node = Node.Next
	}

	return Node.Val
}

// AddAtHead 将数据为val的节点添加到第一位 √
func (this *MyLinkedList) AddAtHead(val int) {
	Node := &ListNode{Val: val, Next: this.Head}
	this.Head = Node
	this.size++
}

// AddAtTail 将数据为val的节点添加到最后一位 √
func (this *MyLinkedList) AddAtTail(val int) {
	this.size++
	if this.Head == nil {
		this.Head = &ListNode{Val: val}
		return
	}
	Node := this.Head
	for Node.Next != nil {
		Node = Node.Next
	}
	Node.Next = &ListNode{Val: val}
}

// AddAtIndex 将数据为val的节点插入到第index个节点之前;若链表长度为index,则放置到最后一位;若超过链表长度不做修改 √
func (this *MyLinkedList) AddAtIndex(index int, val int) {
	if this.size == index {
		this.AddAtTail(val)
		return
	}
	if this.size < index {
		return
	}
	//有第index节点
	//如果index=0,则需要改动首结点,直接待用addAtHead
	if index == 0 {
		this.AddAtHead(val)
		return
	}

	cur := this.Head
	Node := cur

	//0 1 2 3	;index=2
	for ; index > 1; index-- {
		Node = Node.Next
	}
	Node.Next = &ListNode{Val: val, Next: Node.Next}
	this.Head = cur
	this.size++
}

// DeleteAtIndex 删除第index个节点
func (this *MyLinkedList) DeleteAtIndex(index int) {
	if index+1 > this.size {
		return
	}

	// 0 1 2 3	;index=0
	//如果index=0,依旧需要修改头节点
	if index == 0 {
		this.Head = this.Head.Next
		this.size--
		return
	}

	Node := this.Head
	cur := Node

	0 1 2 3	;index=3,删除最后一个,只需要将最后.next=nil
	//if index+1 == this.size {
	//	for ; index > 1; index-- {
	//		cur = cur.Next
	//	}
	//	cur.Next = nil
	//	this.Head = Node
	//	this.size--
	//	return
	//}
	//
	0 1 2 3	;index=2
	//for ; index > 1; index-- {
	//	cur = cur.Next
	//}
	//cur.Next = cur.Next.Next
	//this.Head = Node
	//this.size--

	for ; index > 1; index-- {
		cur = cur.Next
	}
	if index+1 == this.size {
		cur.Next = nil
		this.size--
		return
	}
	cur.Next = cur.Next.Next
	this.Head = Node
	this.size--
}


使用头节点 推荐**

首先性能足够优秀,而且代码简洁还方便
在这里插入图片描述

//本次目标时建立具有 头节点 的链表(虚拟头节点,但实际就是有头节点)
//链表结构:H* 0 1 2 3
//优势,在对头节点后的节点进行操作会方便

type MyLinkedList struct {
	Size      int
	DummyHead *ListNode
}

// Constructor 使用虚拟头节点时,很关键的一步在在初始化我们的mylinkedlist,我们需要直接对dummyhead分配内存空间,防止后续对首个节点进行操作时出现问题
func Constructor() MyLinkedList {
	return MyLinkedList{DummyHead: &ListNode{}}
}

func (this *MyLinkedList) Get(index int) int {
	//*h 0 1 2 3	;0
	if this.Size <= index {
		return -1
	}

	DummyHead := this.DummyHead
	cur := DummyHead

	for ; index >= 0; index-- {
		cur = cur.Next
	}

	return cur.Val
}

func (this *MyLinkedList) AddAtHead(val int) {

	//if this.Size == 0 {
	//	this.Head = &ListNode{Next: &ListNode{Val: val}}
	//	this.Size++
	//} else {
	//	this.Head.Next = &ListNode{Val: val, Next: this.Head.Next}
	//	this.Size++
	//}

	//newNode := &ListNode{Val: val} // 创建新节点
	//newNode.Next = this.Head.Next  // 新节点指向当前头节点
	//this.Head.Next = newNode       // 新节点变为头节点
	//this.Size++                    // 链表大小增加1

	//上面第一块没想明白,逻辑有问题;第二部分进行整合,本质一样
	this.DummyHead.Next = &ListNode{Val: val, Next: this.DummyHead.Next}
	this.Size++
}

func (this *MyLinkedList) AddAtTail(val int) {
	if this.Size == 0 {
		this.AddAtHead(val)
		return
	}
	DummyHead := this.DummyHead
	cur := DummyHead
	//h* 0 1 2 3 4	;
	for cur.Next != nil {
		cur = cur.Next
	}
	cur.Next = &ListNode{Val: val}
	this.DummyHead = DummyHead
	this.Size++
}

func (this *MyLinkedList) AddAtIndex(index int, val int) {
	//如果index=链表长度,插入到末尾
	if this.Size == index {
		this.AddAtTail(val)
		return
	}
	//如果index>链表长度,什么都不做

	//<长度,插入到index节点前
	//h* 0 1 2 3 4	;2
	if this.Size > index {
		DummyHead := this.DummyHead
		cur := DummyHead

		for ; index > 0; index-- {
			cur = cur.Next
		}
		cur.Next = &ListNode{Val: val, Next: cur.Next}
		this.DummyHead = DummyHead
		this.Size++
	}

}

func (this *MyLinkedList) DeleteAtIndex(index int) {
	//h* 0 1 2 3 4	;0

	if this.Size > index {
		DummyHead := this.DummyHead
		cur := DummyHead

		for ; index > 0; index-- {
			cur = cur.Next
		}
		cur.Next = cur.Next.Next
		this.DummyHead = DummyHead
		this.Size--
	}

}

http://www.niftyadmin.cn/n/5299983.html

相关文章

YOLOv5算法进阶改进(10)— 更换主干网络之MobileViTv3 | 轻量化Backbone

前言:Hello大家好,我是小哥谈。MobileViTv3是一种改进的模型架构,用于图像分类任务。它是在MobileViTv1和MobileViTv2的基础上进行改进的,通过引入新的模块和优化网络结构来提高性能。本节课就给大家介绍一下如何在主干网络中引入MobileViTv3网络结构,希望大家学习之后能够…

.NET国产化改造探索(二)、银河麒麟安装人大金仓数据库

随着时代的发展以及近年来信创工作和…废话就不多说了&#xff0c;这个系列就是为.NET遇到国产化需求的一个闭坑系列。接下来&#xff0c;看操作。 上一篇介绍了如何安装银河麒麟操作系统&#xff0c;这篇文章详细介绍下如何在银河麒麟操作系统上安装人大金仓数据库。 准备安…

AI数据微调找免费GPU遇阻之路

赶在如火如荼的2023 AI的尾声&#xff0c;开始研究AI&#xff0c;在了解了当前技术的发展以及试用了多个AI模型和平台之后&#xff0c;计划本地安装Llama.cpp&#xff0c;利用积累的威胁建模数据和检测规则数据进行数据微调&#xff0c;实现自动化威胁建模和AI静态分析。但是没…

【愚公系列】2023年12月 HarmonyOS应用开发者基础认证(完美答案)

&#x1f3c6; 作者简介&#xff0c;愚公搬代码 &#x1f3c6;《头衔》&#xff1a;华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xf…

SpringAMQP的使用方式

MQ介绍 MQ&#xff0c;中文是消息队列&#xff08;MessageQueue&#xff09;&#xff0c;字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。 比较常见的MQ实现&#xff1a; ActiveMQ RabbitMQ RocketMQ Kafka 几种常见MQ的对比&#xff1a; RabbitMQActiveM…

梯度下降法

前言&#xff1a;在均方差损失函数推导中&#xff0c;我使用到了梯度下降法来优化模型&#xff0c;即迭代优化线性模型中的和。现在进一步了解梯度下降法的含义以及具体用法。 一、梯度下降法(入门级理解&#xff09; 定义&#xff1a;梯度下降是一种用于最小化损失函数的优化…

返利机器人的实现原理:从技术到收益的全面解析

返利机器人的实现原理&#xff1a;从技术到收益的全面解析 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在电商时代&#xff0c;许多消费者对返利机器人并不陌生。…

【Linux】手把手教你做一个简易shell(命令行解释器)

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;自己能写出一个简易shell&#xff08;命令行解释器…