当前位置:主页 > 查看内容

学会链表中LeetCode三道题

发布时间:2021-07-16 00:00| 位朋友查看

简介:系列文章目录 文章目录 系列文章目录 前言 一、链表的中间结点 1.题目描述 2.解题思路 二、链表的倒数第k个结点 1.题目描述 2.解题思路 三、合并两个排序的链表 1.题目描述 2.解题思路 总结 前言 一、链表的中间结点 链表的中间结点 1.题目描述 给定一个头结……

在这里插入图片描述

系列文章目录



前言


在这里插入图片描述

一、链表的中间结点

链表的中间结点

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;
}

总结

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

在这里插入图片描述

;原文链接:https://blog.csdn.net/qq_44918090/article/details/115749385
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐