前言
多的不说,先说重点,链表的核心解题点,都和链表的基本操作有关:添加、删除、翻转、头结点
解题思路
核心的思路就两个:
- 单链表需要往前倒数数的,考虑快慢指针
- 反转、删除、等基础操作,都依赖虚拟头节点,即当前位置k-1的节点,需要提前保存
删除倒数第n个链表节点 middle leetcode 19
时间3分钟
Golang
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeNthFromEnd(head *ListNode, n int) *ListNode {
h := &ListNode{Next: head}
cnt := 0
slowNode := h
//倒数一般都是快慢指针
//倒数第x个 那就距离第x个遍历到最后1个就行
for node := h;node != nil;node=node.Next{
if node.Next == nil{
snodeNxt := slowNode.Next
slowNode.Next = snodeNxt.Next
}
if cnt >= n{
slowNode = slowNode.Next
}
cnt++
}
return h.Next
}
删除链表的重复值节点 middle leetcode 82
删除链表的第n个节点,比较简单,一个hash统计,一个链表删除 删除注意记录上一个节点就可以搞定
Golang
func deleteDuplicates(head *ListNode) *ListNode {
m := make(map[int]int)
h := &ListNode{Next: head}
for node:=head;node!=nil;node=node.Next{
m[node.Val]++
}
lastNode := h
for node:=head;node!=nil;node=node.Next{
if m[node.Val]>=2{
lastNode.Next = node.Next
}else{
lastNode = node
}
}
return h.Next
}
旋转链表 middle leetcode 61
首先转换题意 等价于后k个节点插入到前面
后k个节点插入到链表首部 这个操作依赖4个节点 1. 倒数k+1个节点 断链后 前半部分的尾巴节点, 2. 断链后 后半部分首、尾节点 3. 虚拟头节点
如果K>=len链表长度,可以理解到,本质超过长度的部分可以算一个周期,直接求余,剩下来的长度仍然是后k%len 个要移动插入的节点 比如 k = 4 0,1,2 2往右边移动4次,本质相当于往右边移动1次 = 4 % 3
Golang
func rotateRight(head *ListNode, k int) *ListNode {
// 特殊判断只有1个或者为空的情况
if head == nil || head.Next == nil{
return head
}
h := &ListNode{Next: head}
cnt := 0
var oldTailNode *ListNode
var lastKNode *ListNode
lastKNode = h
for node:=head;node!=nil;node=node.Next{
cnt++
oldTailNode = node
}
k %= cnt
// 如果不需要移动也直接返回
if k == 0{
return head
}
cnt = 0
for node:=head;node!=nil;node=node.Next{
cnt++
if cnt >= k+1{
lastKNode = lastKNode.Next
}
}
newHead := lastKNode.Next
lastKNode.Next = oldTailNode.Next
oldTailNode.Next = head
h.Next = newHead
return h.Next
}
总结
- 核心操作:链表基础操作(添加、删除、翻转、头结点运用)是解题根基,贯穿各类题型。
- 解题思路:单链表往前倒数,用快慢指针;涉及反转、删除,借助虚拟头节点,提前保存当前位置 k - 1 的节点。
- 例题解法
- 删除倒数第 n 个链表节点:利用快慢指针定位待删节点前驱,实现删除。
- 删除链表的重复值节点:哈希表统计频次,结合链表删除操作。
- 旋转链表:转换题意,依据节点位置关系,调整链表结构 。