leetcode-82

224 阅读2分钟

题目描述:集体描述见原题。简单来说就是去掉链表中重复元素,只保留没有重复出现的数。

解题思路:这道题首选递归解法,因为比较简单。递归解法分为两种情况,第一种是头节点和头节点下一个节点值相同,这种情况删除头节点及之后所有值相同节点,递归处理之后的节点。第二种情况是头节点不重复,直接递归处理头节点下一个节点。非递归解法可以更方便地了解具体删除过程,需要三个指针。一个指针指向当前处理节点,一个指针记录当前节点前一个节点位置,一个指针向前遍历,具体过程见代码。

具体代码:

// 递归解法
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个用例,还不到总测试用例数量的四分之一,悲伤逆流成河。成都发现了病例,去不了了,去蹲漂亮小姐姐们的机会没得了,悲伤逆流成河。