链表相关面试题第一篇

Posted 森明帮大于黑虎帮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表相关面试题第一篇相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

系列文章目录



前言


在这里插入图片描述

一、移除链表元素

移除链表元素

1.题目描述

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.解题思路

解题方法1:

  1. 判断头节点是否为空
  2. 定义两指针,一指针prev=NULL,一指针等于头指针
  3. 遍历链表,判断两种情况,一种头节点就是val,一种头节点不为val
  4. 不是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:

  1. 定义一个哨兵节点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:

  1. 直接使用三个指针翻转,定义指针n1=NULL,n2=head,n3=head->next
  2. 先翻转,后迭代
  3. 翻转就是指针指向的方向调头,n2->next=n1
  4. 迭代就是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:

  1. 头插法,把原来的节点头插到头节点上
    在这里插入图片描述

代码如下:

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.解题思路

  1. 运用快慢指针解法,快指针走两步,慢指针走一步,注意结束条件即可
    在这里插入图片描述
    代码如下:
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个节点

链表的倒数第k个节点

1.题目描述

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
在这里插入图片描述

2.解题思路

  1. 运用双指针法
  2. 一个指针先走k步
  3. 在两指针一起走,结束的时候就是倒数第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;
}

总结

以上就是今天要讲的内容,本文仅仅简单介绍了链表几道经典题的解法,后面会继续发布链表后面的题目解法,希望大家多多支持。还有,如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。

在这里插入图片描述

以上是关于链表相关面试题第一篇的主要内容,如果未能解决你的问题,请参考以下文章

链表相关面试题第三篇

每日10道JAVA面试题第一篇

LeetCode刷题第一周

剑指offer系列刷题第一篇——寻找单身狗

爆肝20万字Java面试题第二版(背诵版)

爆肝20万字Java面试题第二版(背诵版)