手撕C语言题典——环形链表的约瑟夫问题

2024-05-15 14:20

本文主要是介绍手撕C语言题典——环形链表的约瑟夫问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

前言 

一.故事背景

二.题目 

​编辑三.思路

1)数组

​编辑2) 循环链表

四.代码实现 


 

搭配食用更佳哦~~

数据结构之单单单——链表-CSDN博客

数据结构之单链表的基本操作-CSDN博客

前面学了单链表的相关知识,我们来尝试做一下关于单链表的经典算法题~ 

前言 

      这次是牛客上的一道题,是循环链表的经典应用,讲的是一个老六用自己的聪明才智躲过被杀的命运。

环形链表的约瑟夫问题_牛客题霸_牛客网 (nowcoder.com)https://www.nowcoder.com/practice/41c399fdb6004b31a6cbb047c641ed8a?tpId=196&tqId=37145&ru=/exam/oj

一.故事背景

        Josephus 问题是一个古老而著名的问题,最早的记载来自犹太历史学家弗拉维奥·约瑟夫斯(FlaviusJosephus),他在犹太战争中被罗马军队包围,为了不被俘虏,他和他的 39 个战友决定自杀,但是他们并不想自己亲手杀死自己,于是决定站在一个圆圈里,从一个人开始,每报数到第 14 个人,第 14 个人就会被杀掉,然后从下一个人开始重新报数,直到最后只剩下一个人,那个人就可以幸存。

Josephus(真是纯老六)要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

二.题目 

e10ea47231e4436683a9b4ba91c1a6c1.png三.思路

1)数组

 用数组的话我们需要先申请空间,然后再计数,每记到2就嘎掉它,可以给他赋值一个数组不存在的数比如 0 ,当报数到最后一个时我们需要返回数组最开始也就是下标为 0的时候,当剩下最后一个时就得到了活着的那一个,因为数组比较麻烦而且本篇要讲的是环形链表,所以这个代码就不写了,仅叙述一下思路

3ddf0946dfcc4b059fabacc89cf15f0c.png2) 循环链表

     顾名思义,循环链表就是把原本线性的链表成环,如何实现呢?我们都知道链表尾节点指针指向NULL,所以我们把这个指针指向头节点就可以搞出一个循环链表。

  和上一个思路一样,我们依旧让他们循环报数,报到 2 的嘎掉,在删除这个节点的同时我们需要将前一个节点的 next 指针指向被嘎节点的下一个指针,这样才能使链表连续起来

c3de780573a944219f8a1c8a019682a6.png

虽然画的蛮乱的,大致意思一样,最终结果就是第三个节点自己指向自己。

总结思路就两步:

  • 创建带环链表
  • 计数,嘎节点

四.代码实现 

/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param n int整型 * @param m int整型 * @return int整型*/
#include <stdlib.h>
typedef struct ListNode ListNode;
//创建节点
ListNode* buyNoded(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 = buyNoded(1);ListNode* ptail = phead;for (int i = 2; i<= n; i++) {ptail->next = buyNoded(i);ptail = ptail->next;}ptail->next = phead;return ptail;
}
int ysf(int n, int m ) {// write code here//创建带环链表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;
}

这道题到这就结束啦~虽然循环链表写起来比较麻烦要封装好多函数,但封装完就好写啦~~

    🎈🎈完结撒花🎈🎈  

 

这篇关于手撕C语言题典——环形链表的约瑟夫问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992057

相关文章

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决