您的位置:首页 > 职场人生

寻找链表中倒数第k个结点

2017-07-08 15:01 316 查看
//1.相当于遍历链表两次,第一次结点指针全部入栈,第二次找到倒数第k个结点
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
//注意防御性编程:
//1.如果k大于链表的个数.
//2.如果k为0
//3.如果链表为空
if ( NULL == pListHead || 0 == k )
return NULL;

stack<ListNode*> s;

while ( NULL != pListHead ){
s.push( pListHead );
pListHead = pListHead->next;
}

if ( s.size( ) < k )
return NULL;

for ( size_t i = 1; i < k; ++i )
s.pop( );

return s.top( );
}

//2.只需遍历链表一次的解法:
//大致思路: 两个指针都指向头节点,第一个指针先在链表上走k-1步,此时第二个指针和第一个指针同时向后走,当第一个指针走到结尾时,第二个指针的指向就是倒数第k个结点。
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
if ( NULL == pListHead || 0 == k )
return NULL;

size_t count = 0;
ListNode* pNode1 = pListHead;
ListNode* pNode2 = pListHead;

//根据我们思路以及前面判断过的k不等于0. 所以k-1至少为0.
for ( size_t i = 0; i < k-1; ++i, ++count ){
if ( NULL == pNode1 )
return NULL;

pNode1 = pNode1->next;
}
//注意,如果k给的有问题,如大于链表元素个数
//程序到这时pNode1已有可能为NULL
if ( NULL == pNode1 )
return NULL;

while ( NULL != pNode1->next ){
++count;

pNode1 = pNode1->next;
pNode2 = pNode2->next;
}

if ( count+1 < k/*count + 1 为链表中结点个数*/ )
return NULL;
else
return pNode2;
}
//注意,我们写完这种思路后再来分析,和第一种思路相比,第二种思路确实只遍历了链表一次。
//可是第二种思路边界情况太多,需要注意可能会出错地方太多,相比之下,第一种思路通俗易懂也不易出错。
//注意有unsigned int 类型变量时一定要小心注意 这种变量值为0 时减去一个正数。

//下面是 剑指offer上代码,比上述代码简洁,也少去了不必要的判断.

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
if ( NULL == pListHead || 0 == k )
return NULL;

ListNode* pAhead = pListHead;
ListNode* pBehind = NULL;

for ( size_t i = 0; i < k-1; ++i ){
if ( NULL != pAhead->next )
pAhead = pAhead->next;
else
return NULL;
}

pBehind = pListHead;
while ( NULL != pAhead->next ){
pAhead = pAhead->next;
pBehind = pBehind->next;
}

return pBehind;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息