链表题目
结构
struct ListNode {
ListNode(int x) :
val(x), next(nullptr) {
}
int val;
struct ListNode *next;
};
1.求链表中结点个数
int GetList_num(ListNode*head)
{
if (head == nullptr)
return 0;
int count = 0;
ListNode*p = head;
while (p){
count++;
p = p->next;
}
return count;
}
2.反转一个单链表
ListNode*reverse_list(ListNode*head){
if (head == nullptr || head->next == nullptr)
return head;
ListNode * p_rhead = nullptr;
ListNode * p_current = head;
/*此处进行特别处理,当只有一个结点的时候就这么搞*/
while (p_current)
{
ListNode*ptemp = p_current;
p_current = p_current->next;
ptemp->next = p_rhead;
p_rhead = ptemp;
}
return p_rhead;
}
3.查找单链表中倒数第k个结点
ListNode*Get_kthnode(ListNode*phead, int k){
if (k == 0 || phead == nullptr)
return nullptr;
/*如果结点为空或者没有结点返回空*/
ListNode*pheadA = phead;
ListNode*pheadB = phead;
while (k < 1 && pheadA != nullptr)
{
k--;/*先从头往后找(k-1)个位置*/
pheadA = pheadA->next;
}/*此时进行判断k是否是大于1的,如果大于1说明结点不够k个*/
if (k>1 || pheadA == nullptr)
return nullptr;
while (pheadA->next)
{
pheadB = pheadB->next;
pheadA = pheadA->next;
}
return pheadB;
//然后往后面数,一个指针为空的时候另一个指针所指向的就是要求的结点位置
}
4.倒序打印链表
void Rprintlist(ListNode*head)
{/*利用栈,先进后出的性质去,倒序输出一个链表*/
stack<ListNode*>s;
ListNode*p = head;
while (p){
s.push(p);
p = p->next;
}//使用栈这种结构来存储每个结点
while (!s.empty())//然后将栈内的元素挨个弹出
{
p = s.top();
cout << p->val;
s.pop();
}
}
5.判断单链表是否有环
bool hascircle(ListNode*head){
ListNode*pfast = head;
ListNode*pslow = head;
/*此方法使用快慢指针的方式进行处理
当快指针追上慢指针的时候,就说明有环
*/
while (pfast != nullptr&&pfast->next != nullptr)
{
pfast = pfast->next->next;
pslow = pslow->next;
if (pslow == pfast)
return true;
}
return false;
}
6.寻找链表中间结点
ListNode*GetMiddle_node(ListNode*head)
{
if (head == nullptr || head->next == nullptr)
return head;
ListNode*pheadA = head;
ListNode*pheadB = head;
while (pheadA->next != nullptr){
pheadA = pheadA->next;
pheadB = pheadB->next;
if (pheadA->next != nullptr)
pheadA = pheadA->next;
/*上面已经走了一步,这里又多走一步*/
}
return pheadB;
}
/*快慢指针,快指针每次走两步,慢指针每次走一步,当快指针走到末尾的时候,慢指针刚好走到中间位置*/
7.合并两个有序的单链表
ListNode*merge_list(ListNode* l1, ListNode*l2)
{
ListNode dummy(INT_MIN);
ListNode*tail = &dummy;
while (l1&&l2)//两者都为真的时候才会往下执行,当有一个为假的时候就停止呢
{
if (l1->val < l2->val)
{
tail->next = l1;
l1 = l1->next;
}
else
{
tail->next = l2;
l2 = l2->next;
}
tail = tail->next;
}//到下面这句的时候肯定有一个为假
return tail->next = l1 ? l1 : l2;
}//如果l1为空的时候,将l2连接起来;当l2为空的时候,将l1连接起来
8.判断两个单链表是否有交点
题目:两个单链表,人字形结构的链表,从两个链表的头开始,然后挨个遍历,遍历到最后的时候,如果结点相同,那么就说明两个链表有交点
bool IsInter_sect(ListNode*phead1, ListNode*phead2){
if (phead1 == nullptr|| phead2 == nullptr)
return false;
ListNode*ptail1 = phead1;
while (ptail1->next != nullptr)
ptail1 = ptail1->next;
ListNode*ptail2 = phead2;
while (ptail2->next != nullptr)
ptail2 = ptail2->next;
return ptail1 == ptail2;
}
9.求两个单链表相交的第一个结点
ListNode*Getfirst_common_node(ListNode*phead1, ListNode*phead2)
{
if (phead1 == nullptr || phead2 == nullptr)
return nullptr;
int len1 = 1;
ListNode*ptail1 = phead1;
while (ptail1->next != nullptr)
{
len1++;
ptail1 = ptail1->next;
}
int len2 = 1;
ListNode*ptail2 = phead2;
while (ptail2->next != nullptr)
{
len2++;
ptail2 = ptail2->next;
}
if (ptail1 != ptail2)
return nullptr;
/*首先去判断两个链表是否有交点,并统计链表结点个数*/
ListNode*pnode1 = phead1;
ListNode*pnode2 = phead2;
/*如果l1的长度大于l2那么就遍历l1,就从l1开始遍历,否则从l2开始遍历*/
if (len1 > len2)
{
int k = len1 - len2;
while (k--)
pnode1 = pnode1->next;
}
else
{
int k = len2 - len1;
while (k--)
pnode2 = pnode2->next;
}
while (pnode1 != pnode2)
{
pnode1 = pnode1->next;
pnode2 = pnode2->next;
}
return pnode1;
}
/*当长的减去短的时候,就处于同一位置了,然后同时往后跑,当指针指向的内容相同的时候,就可以找到交点的位置*/
10.已知一个链表有环,求链表的交点
ListNode*get_first(ListNode*head)
{
ListNode*slow = head;
ListNode*fast = head;
while (fast&&fast->next != nullptr)
{
slow = slow->next;
fast = fast->next->next;
/*快慢指针问题,这里是有规律的,另外找一个指针A,A指针从头开始跑
快慢指针相遇的地方为B,此时A和B同时往后面走,当两个结点相遇的时候,
此结点为环的结点
*/
if (fast == slow)
{
ListNode*slow2 = head;
while (slow2 != slow)
{
slow = slow->next;
slow2 = slow->next;
}
return slow2;
}
return nullptr;
}
}
总结
以上包括了大部分链表的大部分笔试题目,一般互联网公司的笔试题目是不会出这种测试题目,都会讲一个故事,让你通过故事去建立相对应的模型。
但是这种题目非常经典,一般出现在现场面试或笔试中。