剑指offer-面试题16:反转链表

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

思路:如果全部改变指针指向,则可以反转链表,那么对当前结点,要指向它前面的结点,同时它的下一节点要在下一步中指向自己,所以函数没执行一步,需要前一结点和下一结点,防止链表断裂。当前结点的下一结点为NULL时,表明已经到尾结点,执行过程结束,同时将尾结点置为新的表头。

ListNode* ReverseList(ListNode* pListHead)
{
	ListNode* pReverseHead = NULL;
	ListNode* pNode = pListHead;
	ListNode* pPrev = NULL;
	while(pNode != NULL)
	{
		ListNode* pNext = pNode->m_pNext;
		if(pNext == NULL)
			pReverseHead = pNode;
			
		pNode->m_pNext = pPrev;
		pPrev = pNode;
		pNode = pNext;
	}
	return pReverseHead;
}

问题扩展:用递归实现同样的反转链表的功能。

思路:问题细分,假设头结点后面的链表已经反转,只要将头结点插入到子链表后尾部就可以了。也就是将子链表的尾结点指向头结点。在寻找子链表尾结点的时候犯了一点错误,一开始用的方法是遍历子链表寻找尾结点。实际上尾结点就是头结点的下一结点。错误的根源是我以为头结点和子链表已经断开,所以无法直接获取头结点的下一结点。实际上由于利用了递归算法,链表的反转是从表尾开始的,直到后面n-1个结点已经反转了头结点仍然是指向它在原链表中的下一结点的。

ListNode* ReverseList(ListNode* pListHead)
{
	if(pListHead == NULL || pListHead->m_pNext == NULL)
		return pListHead;
	else
	{
		ListNode* NewHead = ReverseList(pListHead->m_pNext);
		pListHead->m_pNext->m_pNext = pListHead;
		pListHead->m_pNext = NULL;
		return NewHead;
	}
}


你可能感兴趣的:(剑指offer-面试题16:反转链表)