【剑指offer】3.4 代码的鲁棒性

面试题15:链表中倒数第k个结点

题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。链表结点定义如下:

struct ListNode
{
	int       m_nValue;
	ListNode* m_pNext;
};

解答:代码如下:

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
	if(NULL == pListHead || k <= 0)
	{
		return NULL;
	}
        
	ListNode *pFast = pListHead;
	ListNode *pSlow = pListHead;
	for(int i = 0;i < k - 1;++i)
	{
		if(pFast->m_pNext != NULL)
		{
			pFast = pFast->m_pNext;
		}
		else
		{
			return NULL;
		}
	}
        
	while(pFast->m_pNext != NULL)
	{
		pFast = pFast->m_pNext;
		pSlow = pSlow->m_pNext;
	}
        
	return pSlow;
}

面试题16:反转链表

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

struct ListNode
{
	int       m_nKey;
	ListNode* m_pNext;
};

解答:代码如下:

ListNode* ReverseList(ListNode* pHead)
{
	if(NULL == pHead)
	{
		return NULL;
	}
	if(NULL == pHead->m_pNext)
	{
		return pHead;
	}
        
	ListNode *pLeft = pHead;
	ListNode *pMid = pHead->m_pNext;
	ListNode *pRight = pMid->m_pNext;
	while(pMid != NULL)
	{
		pMid->m_pNext = pLeft;
		pLeft = pMid;
		pMid = pRight;
		if(pRight != NULL)
		{
			pRight = pRight->m_pNext;
		}
	}
	pHead->m_pNext = NULL;
        
	return pLeft;
}

面试题17:合并两个排序的链表

题目:输入两个递增有序的链表,合并者两个链表并使新链表中的结点仍然是按照递增排序的。链表结点定义如下:

struct ListNode
{
	int       m_nValue;
	ListNode* m_pNext;
};

解答:1.非递归

ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
	if(NULL == pHead1 && NULL == pHead2)
	{
		return NULL;
	}
	if(NULL == pHead1)
	{
		return pHead2;
	}
	if(NULL == pHead2)
	{
		return pHead1;
	}
        
	ListNode *pNode1 = pHead1;
	ListNode *pNode2 = pHead2;
	ListNode *newListHead = (pNode1->m_nValue < pNode2->m_nValue) ? pNode1 : pNode2;
	ListNode *newListNode = newListHead;
	if(newListHead == pNode1)
	{
		pNode1 = pNode1->m_pNext;
	}
	else
	{
		pNode2 = pNode2->m_pNext;
	}
        
	while(pNode1 && pNode2)
	{
		if(pNode1->m_nValue < pNode2->m_nValue)
		{
			newListNode->m_pNext = pNode1;
			pNode1 = pNode1->m_pNext;
		}
		else
		{
			newListNode->m_pNext = pNode2;
			pNode2 = pNode2->m_pNext;
		}
		newListNode = newListNode->m_pNext;
	}
        
	if(pNode1)
	{
		newListNode->m_pNext = pNode1;
	}
        
	if(pNode2)
	{
		newListNode->m_pNext = pNode2;
	}
        
	return newListHead;
}

2.递归

ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
	if(NULL == pHead1)
	{
		return pHead2;
	}
	if(NULL == pHead2)
	{
		return pHead1;
	}
    
	ListNode *newListHead = NULL;

	if(pHead1->m_nValue < pHead2->m_nValue)
	{
		newListHead = pHead1;
		newListHead->m_pNext = Merge(pHead1->m_pNext,pHead2);
	}
	else
	{
		newListHead = pHead2;
		newListHead->m_pNext = Merge(pHead1,pHead2->m_pNext);
	}
        
	return newListHead;
}

面试题18:数的子结构

题目:输入两棵二叉树A和B,判断B是不是A的子结构。二叉树结点的定义如下:

struct BinaryTreeNode
{
	int             m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

解答:代码如下:

bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	if(NULL == pRoot2)
	{
		return true;
	}

	if(NULL == pRoot1)
	{
		return false;
	}

	if(pRoot1->m_nValue != pRoot2->m_nValue)
	{
		return false;
	}

	return DoesTree1HaveTree2(pRoot1->m_pLeft,pRoot2->m_pLeft) 
		&& DoesTree1HaveTree2(pRoot1->m_pRight,pRoot2->m_pRight);
}

bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	bool res = false;
	if(pRoot1 != NULL && pRoot2 != NULL)
	{
		if(pRoot1->m_nValue == pRoot2->m_nValue)
		{
			res = DoesTree1HaveTree2(pRoot1,pRoot2);
		}

		if(!res)
		{
			res = HasSubtree(pRoot1->m_pLeft,pRoot2);
		}

		if(!res)
		{
			res = HasSubtree(pRoot1->m_pRight,pRoot2);
		}
	}

	return res;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值