【链表经典算法OJ题】(2)

4.链表的中间节点

单链表相关经典算法OJ题4: 链表的中间结点
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/middle-of-the-linked-list/

思路:

问题的关键也在于我们无法直接得到单链表的长度 n,常规方法也是先遍历链表计算 n,再遍历一次得到第 n / 2 个节点,也就是中间节点。

如果想一次遍历就得到中间节点,也需要耍点小聪明,使用「快慢指针」的技巧:

我们让两个指针 slow 和 fast 分别指向链表头结点 head。

每当慢指针 slow 前进一步,快指针 fast 就前进两步,这样,当 fast 走到链表末尾时,slow 就指向了链表中点。

实现代码:

复制代码
/**
 * Definition for singly-linked list.
 * 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;
}

5.环形链表的约瑟夫问题

循环链表经典应⽤-环形链表的约瑟夫问题环形链表的约瑟夫问题_牛客题霸_牛客网编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。。题目来自【牛客题霸】https://www.nowcoder.com/practice/41c399fdb6004b31a6cbb047c641ed8a

思路:

  • 成环, 返还tail结点
  • 初始化前哨指针,和当前指针
  • 遍历计数,当技术等于m了,则摘掉当前结点,从下个结点开始
  • 返回最一个指针,即当前指针的val

代码实现:

复制代码
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param n int整型 
 * @param m int整型 
 * @return int整型
 */
typedef struct ListNode ListNode;
//创建节点
ListNode* buyNode(int x)
{
	ListNode* node = (ListNode*)malloc(sizeof(ListNode));
	if (node == NULL)
	{
		exit(1);

	}
	node->val = x;
	node->next = NULL;
	return node;
}

//创建带环链表
ListNode*createCircle(int n) 
{
	//先创建第一个节点
	ListNode* phead = buyNode(1);
	ListNode* ptail = phead;
	for (int i = 2; i <= n; i++)
	{
		ptail->next = buyNode(i);
		ptail = ptail->next;
	}
	//首尾相连,链表成环
	ptail->next = phead;
	return ptail;
}

int ysf(int n, int m)
{
	//1.根据n创建带环链表
	ListNode* prev = createCircle(n);
	ListNode* pcur = prev->next;
	int count = 1;
	//当链表中只有一个节点的情况
	while (pcur->next!=pcur)
	{
		if (count == m)
		{
			//销毁pcur节点
			prev->next = pcur->next;
			free(pcur);
			pcur = prev->next;
			count = 1;
		}
		else
		{
			//此时不需要销毁节点
			prev = pcur;
			pcur = pcur->next;
			count++;
		}
	}
	//此时剩下的一个节点就是要返回的节点里的值
	return pcur->val;
}

6.合并两个有序链表

单链表相关经典算法OJ题6: 分割链表
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/partition-list-lcci/

思路:

创建大小链表,比x大的插入大链表,比x小的插入小链表。

代码实现:

复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x)
{
	//创建两个带头链表
	ListNode* lessHead, * lessTail;
	ListNode* greaterHead, * greaterTail;
	lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));
	greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));

	//遍历原链表,将原链表的节点尾插到大小链表中
	ListNode* pcur = head;
	while(pcur)
	{
		if (pcur->val < x)
		{
			//尾插到小链表中
			lessTail->next = pcur;
			lessTail = lessTail->next;
		}
		else
		{
			//尾插到大链表中
			greaterTail->next = pcur;
			greaterTail = greaterTail->next;

		}
		pcur = pcur->next;

	}

    //修改大链表的尾节点的next指针指向
	greaterTail->next = NULL;//若不加这一行,代码会出现死循环

	//小链表的尾节点和大链表的第一个有效节点首尾相接
	lessTail->next = greaterHead->next;


	ListNode* ret = lessHead->next;

	free(lessHead);
	free(greaterHead);
	lessHead = greaterHead = NULL;

	return ret;
}

本篇文章介绍了题目的部分解法。如果本篇有补充的地方,欢迎私信我或在评论区指出,期待与你们共同进步。

相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
m0_547486663 天前
《数据结构教程》全套 PPT课件2026
数据结构
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法