题目:输入一个链表,输出链表中倒数第K个节点。为符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个节点。例如,一个链表有6个节点,从头结点开始他们的值依次是1,2,3,4,5,6,。这个链表的倒数第3个节点是值为4的结点。
struct Node
{
int _value;
Node* _next;
Node(const int x)
:_value(x)
, _next(NULL)
{}
};
思路:
定义两个指针,第一指针先走k-1步,第二个指针不动,当从第k步起,两个指针一起动(两个指针的距离始终是k-1)。当第一个指针走到为节点时,第二个指针恰好是倒数第k个节点。
Node* FindKthToTail(Node* pHead, size_t k)
{
if (pHead == NULL || k <= 0)
return NULL;
Node* Front = pHead;
Node* Behind = NULL;
for (int i = 0; i < k - 1; ++i)
{
if (Front->_next != NULL)
Front = Front->_next;
else
return NULL;
}
Behind = pHead;
while (Front->_next != NULL)
{
Front = Front->_next;
Behind = Behind->_next;
}
return Behind;
}
扩展:
1.求链表的中间节点,如果链表中节点的总数为奇数,返回中间节点,如果是偶数,返回中间两个节点的任意一个;
思路:
定义两个指针,同时从链表的头结点出发。一个指针走一步,一个指针走两步。当快的指针走到链表尾时,走的慢的指针恰好为链表中间节点。
//求链表的中间节点
Node* FindListMid(Node* head)
{
if (head == NULL)
return NULL;
Node* front = head;
Node* behind = head;
while (front->_next != NULL && front->_next->_next !=NULL)
{
front = front->_next->_next;
behind = behind->_next;
}
return behind;
}
2.判断一个单向链表是否形成环形结构;
思路:定义两个节点,同时从链表的头结点出发。一个指针走一步,一个指针走两步。当快的指针追上了走的慢的指针,说明是环形结构。如果走的快的指针走到了链表尾都没有追上走的慢的指针,说明不是环形结构。
// 判断一个单向链表是否形成了环形结构
bool IsRing(Node* head)//是环 返回 真
{
if (head == NULL)
return false;
Node* front = head;
Node* behind = head;
while (front->_next != NULL && front->_next->_next != NULL)
{
front = front->_next->_next;
behind = behind->_next;
if (front < behind)
return true;
}
return false;
}