ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

LeetCode 83:删除排序链表中的重复元素 Remove Duplicates from Sorted List(Go 题解)

LeetCode 83:删除排序链表中的重复元素 Remove Duplicates from Sorted List(Go 题解) LeetCode 83删除排序链表中的重复元素 Remove Duplicates from Sorted ListGo 题解【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go本文围绕 LeetCode 第 83 题“Remove Duplicates from Sorted List”展开基于本仓库LeetCode-Go中该题目的完整实现与测试用例从题目语义、解题思路、源码逐行剖析到复杂度分析系统讲解如何在 Go 中删除有序链表中的重复结点。读完本文你将掌握单指针遍历有序链表去重的核心手法并学会如何在本仓库中运行该题对应的单元测试进行验证。题目回顾Given a sorted linked list, delete all duplicates such that each element appear only once.题目要求给定一个已排序的链表删除所有重复的结点使得每个元素只出现一次。注意两个前提条件——链表本身有序、只要求删除重复值而非保留唯一性计数这决定了题目可以用线性扫描轻松解决。示例 1Input: 1-1-2 Output: 1-2示例 2Input: 1-1-2-3-3 Output: 1-2-3题目大意删除链表中重复的结点以保障每个结点只出现一次。由于链表有序所有重复值必然连续相邻因此只需比较相邻结点即可完成去重无需借助哈希表等额外数据结构。解题思路本题的核心思路是“按照题意做即可”——维护一个指针cur从头结点开始遍历只要cur还有下一个结点就比较cur.Next.Val与cur.Val若相等说明存在重复值直接将cur.Next指向cur.Next.Next跳过重复结点若不相等指针cur正常前移。整个过程只需遍历一遍链表原地修改结点指针不需要新建链表也不需要额外的存储空间。源码实现与逐行剖析本仓库中该题的实现位于 83. Remove Duplicates from Sorted List.go完整代码如下package leetcode import ( github.com/halfrost/LeetCode-Go/structures ) // ListNode define type ListNode structures.ListNode /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func deleteDuplicates(head *ListNode) *ListNode { cur : head if head nil { return nil } if head.Next nil { return head } for cur.Next ! nil { if cur.Next.Val cur.Val { cur.Next cur.Next.Next } else { cur cur.Next } } return head }链表结点定义代码开头的type ListNode structures.ListNode是一个类型别名直接复用仓库公共包structures中定义的链表结点。真正的结点定义位于 ListNode.go// ListNode 是链接节点 // 这个不能复制到*_test.go文件中。会导致Travis失败 type ListNode struct { Val int Next *ListNode }每个结点包含一个整型值Val和一个指向后继结点的指针Next与 LeetCode 官方对单链表结点的定义完全一致。边界条件处理cur : head if head nil { return nil } if head.Next nil { return head }函数先处理两种边界情况空链表head nil直接返回nil仅一个结点head.Next nil不存在重复可能直接返回原链表。这两步保证了后续循环中cur与cur.Next的安全访问避免空指针解引用。去重主循环for cur.Next ! nil { if cur.Next.Val cur.Val { cur.Next cur.Next.Next } else { cur cur.Next } } return head这是算法的核心值得逐行拆解循环条件cur.Next ! nil确保每次比较都有“当前结点”与“下一结点”这一对相邻结点当cur.Next.Val cur.Val时说明下一结点是重复值。此时执行cur.Next cur.Next.Next即跳过重复结点把当前结点的后继指针直接指向下下个结点。注意这里指针cur不移动因为跳过一个结点后新的cur.Next仍可能与cur.Val相同例如1-1-1这种连续多个重复值需要继续比较当值不相等时cur cur.Next指针正常前进进入下一组相邻结点。一个关键设计点是跳过重复结点时cur保持原地不动。以1-1-2为例cur指向第一个1发现下一个也是1于是cur.Next直接指向2此时循环继续cur.Next值为2与cur.Val值为1不相等cur前移指向2循环结束输出1-2。若在跳过结点时贸然前移cur就会漏判连续三个以上重复值的情况如1-1-1。为什么“按题意做”就够了链表已排序这一前提决定了所有相同值在链表中是连续成片存在的。因此去重等价于“把连续相同值的片段压缩为一个结点”只需要一次线性扫描比较相邻结点即可无需像 0082.Remove-Duplicates-from-Sorted-List-II 那样额外记录重复值并整段删除那道题要求删除所有重复结点、一个不留。本题保留一个副本逻辑上更简单。复杂度分析时间复杂度O(n)其中n为链表长度。cur指针从链头走到链尾每个结点最多被访问常数次空间复杂度O(1)。全程仅使用一个辅助指针cur原地修改链表不申请任何与输入规模相关的额外空间。测试用例验证仓库为该题编写了完整的单元测试位于 83. Remove Duplicates from Sorted List_test.go覆盖了五类典型场景输入期望输出覆盖场景[1, 1, 2][1, 2]题目示例一处重复[1, 1, 2, 2, 3, 3, 3][1, 2, 3]多组重复值连续出现[1, 1, 1, 1, 1, 1, 1, 1][1]全部为相同值压缩为单结点[][]空链表边界[1][1]单结点边界测试的构建方式值得留意测试用例没有直接手写链表而是借助structures包提供的辅助函数完成[]int与链表的双向转换来自 ListNode.go// List2Ints convert List to []int func List2Ints(head *ListNode) []int { ... } // Ints2List convert []int to List func Ints2List(nums []int) *ListNode { if len(nums) 0 { return nil } l : ListNode{} t : l for _, v : range nums { t.Next ListNode{Val: v} t t.Next } return l.Next }其中Ints2List通过哨兵头结点l逐个尾插构造链表并返回l.NextList2Ints则遍历链表收集数值并内置 100 层深度限制一旦链长超过限制会主动panic以拦截可能出现的环状链表避免测试死循环。测试主循环中通过structures.Ints2List(p.one)构造输入链表、调用deleteDuplicates去重后再用structures.List2Ints转回切片并打印从而直观核对输出fmt.Printf(【input】:%v 【output】:%v\n, p, structures.List2Ints(deleteDuplicates(structures.Ints2List(p.one))))在本仓库中运行测试本仓库根目录提供了统一跑测脚本 gotest.sh其内部对所有题目目录执行全量覆盖率测试go test -covermodeatomic -coverprofilecoverage.txt ./leetcode/...若只想单独验证第 83 题的实现与测试可在仓库根目录下直接执行go test -v ./leetcode/0083.Remove-Duplicates-from-Sorted-List/仓库的模块名为github.com/halfrost/LeetCode-Go见 go.mod题目源码内部依赖structures公共包且该包已通过replace github.com/halfrost/LeetCode-Go/structures ./structures指向本地目录因此无需额外联网拉取私有依赖即可在本地完成编译与测试。小结第 83 题是对“有序链表 相邻比较”这一组合的经典考查利用链表有序的天然性质用单指针一遍扫描、原地改链即可完成去重时间复杂度 O(n)、空间复杂度 O(1)。掌握这道题的“跳过重复结点时指针原地不动”这一细节也为后续处理更复杂的链表去重题如保留一个不重复版本的变体、删除全部重复结点等打下基础。【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表