学会链表中LeetCode三道题

16 篇文章 14 订阅

在这里插入图片描述

系列文章目录



前言


在这里插入图片描述

一、链表的中间结点

链表的中间结点

1.题目描述

给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
在这里插入图片描述
在这里插入图片描述

2.解题思路

可以采用快慢指针方法:设置两指针,慢指针速度一次一个结点,快指针一次两个结点。这种方法只遍历了一次链表
在这里插入图片描述

代码如下:

#define _CRT_SECURE_NO_WARNINGS   1
#include<stdio.h>
#include<string.h>
struct ListNode
{
	int val;
	struct ListNode* next;
};
//快慢指针方法
struct ListNode* middleNode(struct ListNode* head)
{
	struct ListNode* fast = head, *slow = head;
	while (fast&&fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
	}
	return slow;
}

二、链表的倒数第k个结点

1.题目描述

链表中倒数第k个结点

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

2.解题思路

同样采用快慢指针方法,让快指针先走k步,结束后快慢指针再次同时出发,快指针结束时慢指针就是走的结果。
在这里插入图片描述
代码如下:

#define _CRT_SECURE_NO_WARNINGS   1
#include<stdio.h>
struct ListNode
{
	int val;
	struct ListNode* next;
};
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;
}

三、合并两个排序的链表

1.题目描述

合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.解题思路

第一种方法:不带哨兵位
在这里插入图片描述
在这里插入图片描述

代码如下:

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
	//判断哪个链表为空,然后返回另一个链表
	if (l1==NULL)
	{
		return l2;
	}
	if (l2 == NULL)
	{
		return l1;
	}
	struct ListNode* head = NULL, *tail = NULL;
	//先去两个链表中小的作为第一个结点
	if (l1->next < l2->next)
	{
		head = tail = l1;
		l1 = l1->next;
	}
	else
	{
		head = tail = l2;
		l2 = l2->next;
	}
	//去链表中其他结点相比较尾插到第一个结点后面
	while (l1&&l2)
	{
		if (l1->val < l2->val)
		{
			tail->next = l1;
			l1 = l1->next;
		}
		else
		{
			tail->next = l2;
			l2 = l2->next;
		}
		tail = tail->next;
	}
	//判断谁还有结束且后面还有结点,直接链接到尾结点上去
	if (l1)
	{
		tail->next = l1;
	}
	if (l2)
	{
		tail->next = l2;
	}
	return head;
}

第二种方法:带哨兵位
代码如下:

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2)
{
	struct ListNode* head = NULL, *tail = NULL;
	//创建一个哨兵位的头结点
	head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
	tail->next = NULL;
	while (l1&&l2)
	{
		if (l1->val < l2->val)
		{
			tail->next = l1;
			l1 = l1->next;
		}
		else
		{
			tail->next = l2;
			l2 = l2->next;
		}
		tail = tail->next;
	}
	if (l1)
	{
		tail->next = l1;
	}
	if (l2)
	{
		tail->next = l2;
	}
	struct ListNode* node = head;
	head = head->next;
	free(node);
	return head;
}

总结

本文仅仅简单介绍了链表常见的三题,这些题目我们以后可能会遇到,我们务必掌握。另外,如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。

在这里插入图片描述

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森明帮大于黑虎帮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值