offer9
输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。
可以先设置一个指针 p1,在链表中前进k步,然后加入新的指针 p2,和 p1同步遍历,直到 p1到尾部,那么 p2就是倒数第k个结点。
需要注意两个地方,当链表长度不足k时,和倒数是从0开始的。
代码:链表附带头节点。
Node* FindKthTotail(Node* pHead, int k)
{
if (!pHead || k<0)
return NULL;
Node* pFront=pHead;
Node* pBehind=pHead;
for (int i=0; i<k; i++)
{
//pFront前进k步,链表长度不足k是返回空指针
pFront=pFront->pNext;
if (pFront==NULL)
return NULL;
}
while (pFront->pNext)
{
pFront=pFront->pNext;
pBehind=pBehind->pNext;
}
if (pBehind==pHead)
return NULL;
return pBehind;
}
offer19
题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。
题目很简单,3个指针即可。
代码:
void ReverseList(ListNode* pHead)
{
ListNode* pPre=NULL;
ListNode* p=pHead->m_pNext;
ListNode* pNext=NULL;
while (p)
{
pNext=p->m_pNext;
p->m_pNext=pPre;
pPre=p;
p=pNext;
}
pHead->m_pNext=pPre;
}
offer35
两个单向链表,找出它们的第一个公共结点。
这个没有考虑链表中有环的情况,类似第9题,可以先遍历两个链表的长度,那么两个链表长的那个指针先向前走差值,然后和短的同步向前,那么两个指针值相同时,就是第一个公共节点。
代码:
bool FindFirstCommon(ListNode* pH1, ListNode* pH2, ListNode* &pResulte)
{
if (!pH1 || !pH2)
return false;
int len1, len2;
len1=len2=0;
ListNode *p1, *p2;
p1=pH1; p2=pH2;
while (p1)
{
len1++;
p1=p1->m_pNext;
}
while (p2)
{
len2++;
p2=p2->m_pNext;
}
//链表长度差值
int k=abs(len1-len2);
p1=pH1; p2=pH2;
//长的链表指针向前k步
if (len1>len2)
{
while (k)
{
p1=p1->m_pNext;
k--;
}
}
else
{
while (k)
{
p2=p2->m_pNext;
k--;
}
}
//找到第一个公共节点
while (p1!=p2)
{
p1=p1->m_pNext;
p2=p2->m_pNext;
}
//没有公共节点
if (!p1)
return false;
pResulte=p1;
return true;
}
编程之美上有考虑环路的情况,以后更新。