链表相关面试题第一篇
Posted 森明帮大于黑虎帮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表相关面试题第一篇相关的知识,希望对你有一定的参考价值。
系列文章目录
文章目录
前言
一、移除链表元素
1.题目描述
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
2.解题思路
解题方法1:
- 判断头节点是否为空
- 定义两指针,一指针prev=NULL,一指针等于头指针
- 遍历链表,判断两种情况,一种头节点就是val,一种头节点不为val
- 不是val则把头节点给prev节点,自己则遍历下去
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val)
{
if(head==NULL)
{
return NULL;
}
struct ListNode* cur=head;
struct ListNode* prev=NULL;
while(cur)
{
struct ListNode* next=cur->next;
if(cur->val==val)
{
if(prev==NULL) //头是val
{
head=next;
free(cur);
cur=next;
}
else
{
prev->next=next;
free(cur);
cur=next;
}
}
else
{
prev=cur;
cur=next;
}
}
return head;
}
解题方法2:
- 定义一个哨兵节点guardHead,这样就不用判断第一个值为val,因为第一个节点哨兵节点永远没有值。
2.遍历链表如果值为val则删除,不为val则遍历下去
代码如下:
struct ListNode* RemoveElements(struct ListNode* head, int val)
{
struct ListNode* guardhead = (struct ListNode*)malloc(sizeof(struct ListNode*));
guardhead->next = head;
struct ListNode* prev = guardhead;
struct ListNode* cur = head;
while (cur)
{
if (cur->val == val)
{
struct ListNode* next = cur->next;
prev->next = next;
free(cur);
cur = next;
}
else
{
prev = cur;
cur = cur->next;
}
}
guardhead->next = head;
free(guardhead);
return head;
}
二、反转单链表
1.题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
2.解题思路
解题思路1:
- 直接使用三个指针翻转,定义指针n1=NULL,n2=head,n3=head->next
- 先翻转,后迭代
- 翻转就是指针指向的方向调头,n2->next=n1
- 迭代就是n1=n2,n2=n3
代码如下:
struct ListNode* reverseList(struct ListNode* head)
{
if (head == NULL || head->next == NULL)
{
return head;
}
struct ListNode* n1 = NULL, *n2 = head, *n3 = head->next;
while (n2)
{
//翻转
n2->next = n1;
//迭代
n2 = n3;
n1 = n2;
if (n3)
{
n3 = n3->next;
}
}
return n1;
}
解题思路2:
- 头插法,把原来的节点头插到头节点上
代码如下:
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur=head;
struct ListNode* newhead=NULL;
while(cur)
{
struct ListNode* next=cur->next;
cur->next=newhead;
newhead=cur;
cur=next;
}
return newhead;
}
三、链表的中间节点
1.题目描述
给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
2.解题思路
- 运用快慢指针解法,快指针走两步,慢指针走一步,注意结束条件即可
代码如下:
struct ListNode* middleNode(struct ListNode* head)
{
//快慢指针
struct ListNode* slow=head,*fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
四、链表的倒数第k个节点
1.题目描述
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
2.解题思路
- 运用双指针法
- 一个指针先走k步
- 在两指针一起走,结束的时候就是倒数第k个节点
代码如下:
struct ListNode* getKthFromEnd(struct ListNode* head, int k)
{
struct ListNode* fast=head,*slow=head;
while(k--)
{
if(fast==NULL)
{
return NULL;
}
fast=fast->next;
}
while(fast)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了链表几道经典题的解法,后面会继续发布链表后面的题目解法,希望大家多多支持。还有,如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。
以上是关于链表相关面试题第一篇的主要内容,如果未能解决你的问题,请参考以下文章