面试题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;
}