算法记录 | Day3 链表

文章介绍了三个关于链表的LeetCode题目,包括如何删除链表中值为特定元素的节点,设计链表的结构和操作,以及如何反转链表。解题思路涉及利用临时节点、前驱节点和后继节点等方法来高效地操作链表。

算法记录 | Day3 链表

LeetCode 203. 移除链表元素

题目

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [], val = 1
输出:[]

示例 2:

输入:head = [7,7,7,7], val = 7
输出:[]

解题思路

  • 临时节点
  • next节点
func removeElements(head *ListNode, val int) *ListNode {
	node := &ListNode{
		Val :0,
		Next: head,
    }
    var tmp = node
	for node.Next != nil{
		if node.Next.Val == val{
             node.Next = node.Next.Next
         }else{
			 node = node.Next
		 }
    }
	return tmp.Next
}

解题思路

LeetCode 707. 设计链表

题目

你可以选择使用单链表或者双链表,设计并实现自己的链表。

单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。

如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始

示例 1:

输入
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]

解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2);    // 链表变为 1->2->3
myLinkedList.get(1);              // 返回 2
myLinkedList.deleteAtIndex(1);    // 现在,链表变为 1->3
myLinkedList.get(1);              // 返回 3

解题思路

/*
这道题要搞清楚head节点和第一个节点的区别
head节点其实是第0号节点
*/

type Node struct {
	val  int   //链表的值
	next *Node //指向下一个节点的指针
}

type MyLinkedList struct {
	head *Node //虚拟头结点
	size int   //定义链表的长度
}

// 对链表的初始化操作
func Constructor() MyLinkedList {
	// 将head节点的值设置为-1,指向空节点
	dummyHead := &Node{
		val:  -1,
		next: nil,
	}
	// 将链表的的长度设置为1
	return MyLinkedList{head: dummyHead, size: 0}
}

// 通过index下标获取对应的val
func (this *MyLinkedList) Get(index int) int {
	// 判断index是否合法
	if (index < 0) || (index > (this.size - 1)) {
		return -1
	}
	// 查找操作
	var cur *Node = this.head //从head节点开始遍历
	for i := 0; i <= index; i++ {
		cur = cur.next //第index节点其实是index+1
	}
	return cur.val
}

// 将节点插入第一个节点之前,head节点之后
func (this *MyLinkedList) AddAtHead(Val int) {
	// 先创建一个新的节点
	var newNode *Node = &Node{val: Val, next: nil}
	// 将新节点指向第一个节点
	newNode.next = this.head.next
	// 然后在将头结点指向新的节点
	this.head.next = newNode
	// 然后将链表的长度加1
	this.size++
}

// 将节点插入到链表的最后面
func (this *MyLinkedList) AddAtTail(Val int) {
	// 先创建一个新的节点
	var newNode *Node = &Node{val: Val, next: nil}
	// 创建一个当前节点,并将它指向head结点,可以说它就是head结点
	cur := this.head
	// 因为是插到结尾
	for cur.next != nil {
		cur = cur.next
	}
	// 此时的cur指向的是nil, 将新节点插入cur之后
	cur.next = newNode
	this.size++
}

// 将节点插入到任意位置
func (this *MyLinkedList) AddAtIndex(index int, Val int) {
	// 条件判断:题目要求
	// 添加的下标大于链表的长度,无效
	if index > this.size {
		return
	} else if index == this.size { //如果 index 等于链表的长度,则该节点将附加到链表的末尾
		this.AddAtTail(Val)
		return
	} else if index < 0 { //如果index小于0,则在头部插入节点。
		index = 0
	}
	// 定义一个新节点
	var newNode *Node = &Node{val: Val, next: nil}
	// 定义一个当前节点,指向头结点
	cur := this.head
	// 在index节点之前index-1处停止
	for i := 0; i < index; i++ {
		cur = cur.next
	}
	// cur.next->index
	newNode.next = cur.next
	cur.next = newNode
	this.size++
}

// 删除节点
func (this *MyLinkedList) DeleteAtIndex(index int) {
	if index > this.size-1 || index < 0 {
		return
	}
	// 从head节点开始
	cur := this.head
	for i := 0; i < index; i++ {
		cur = cur.next
	}
	// 将当前节点指向自已节点下一个节点的下一个节点
	cur.next = cur.next.next
	this.size--
}

/**
 * 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);
 */


解题思路

LeetCode 206.反转链表

题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]
输出:[2,1]

解题思路

  • 前节点,当前节点,后节点
func reverseList(head *ListNode) *ListNode {
    var prev *ListNode
    var next *ListNode

    for head != nil {
        next = head.Next
        head.Next = prev


        prev = head
        head = next
    }
    return prev
}


解题思路

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值