题目描述:集体描述见原题。简单来说就是去掉链表中重复元素,只保留没有重复出现的数。
解题思路:这道题首选递归解法,因为比较简单。递归解法分为两种情况,第一种是头节点和头节点下一个节点值相同,这种情况删除头节点及之后所有值相同节点,递归处理之后的节点。第二种情况是头节点不重复,直接递归处理头节点下一个节点。非递归解法可以更方便地了解具体删除过程,需要三个指针。一个指针指向当前处理节点,一个指针记录当前节点前一个节点位置,一个指针向前遍历,具体过程见代码。
具体代码:
// 递归解法
func deleteDuplicates(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
if head.Val == head.Next.Val { // 头节点重复
for head.Next != nil && head.Val == head.Next.Val {
head = head.Next // 删除所有重复头节点
}
return deleteDuplicates(head.Next) // 递归处理剩下节点
}
head.Next = deleteDuplicates(head.Next) // 如果头节点不重复,直接处理头节点之后所有节点
return head
}
// 非递归解法
func deleteDuplicates(head *ListNode) *ListNode {
if head == nil {
return nil
}
if head.Next == nil {
return head
}
nH := &ListNode{Next:head, Val:101}
pre, cur, tra := nH, nH, head
for tra.Next != nil {
if tra.Val == cur.Val {
tra = tra.Next
} else {
if cur.Next == tra {
pre = cur
cur = cur.Next
} else {
pre.Next = tra
if tra.Next != nil && tra.Next.Val != tra.Val {
pre = tra
}
cur = tra
}
tra = tra.Next
}
}
if tra.Val == cur.Val {
pre.Next = nil
} else {
if cur.Next != tra {
pre.Next = tra
}
}
return nH.Next
}
补充说明:非递归过程有些边界条件需要逐步调试才能发现问题,极为难写,这对我来说是一道困难题目了,最好是拿笔对照代码画一画。第一遍提交只跑过了36个用例,还不到总测试用例数量的四分之一,悲伤逆流成河。成都发现了病例,去不了了,去蹲漂亮小姐姐们的机会没得了,悲伤逆流成河。