当前位置: 首页 > article >正文

【数据结构】_链表经典算法OJ:环形链表的约瑟夫问题

目录

1. 题目链接及描述

2. 解题思路

3. 程序


1. 题目链接及描述

题目链接:环形链表的约瑟夫问题_牛客题霸_牛客网

题目描述:

编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。
下一个人继续从 1 开始报数。
n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?

数据范围: 1≤n,m≤10000
进阶:空间复杂度O(1),时间复杂度O(n);

附:关于约瑟夫问题:

2. 解题思路

总思路:

创建一个环形链表以示当前的n个人,创建指针变量curNode用于遍历链表。创建计数变量count对应遍历的结点,每遍历一个结点则count自增1。当count从1自增到m时,销毁curNode当前指向的结点。从下一结点开始重新遍历,并将count重置为1重新开始递增。

具体实现思路:

为了销毁curNode且保证环形链表的链接,还需记录curNode的前驱结点,记为prevCurNode,每销毁当前的curNode,就令prevCurNode->next=curNode->next;

可通过题目示例辅助思考:

3. 程序

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param n int整型 
 * @param m int整型 
 * @return int整型
 */
typedef struct ListNode ListNode;
// 创建结点
ListNode* CreateNode(int x){
    ListNode* node=(ListNode*)malloc(sizeof(ListNode));
    if(node==NULL){
        exit(1);
    }
    node->val=x;
    node->next=NULL;
    return node;
}
// 创建n结点的带环链表
ListNode* createCircle(int n){
    // 先创建n结点的单向链表
    ListNode* phead=CreateNode(1);
    ListNode* ptail=phead;
    for(int i=2; i<=n; i++){
        ptail->next=CreateNode(i);
        ptail=ptail->next;
    }
    // 再链首尾
    ptail->next=phead;
    return ptail;
}
int ysf(int n, int m ) {
    ListNode* prevCurNode=createCircle(n);
    ListNode* curNode=prevCurNode->next;
    int count=1;
    // 当链表仅剩1个结点时结束
    while(curNode->next!=curNode){
        if(count==m){
            //销毁curNode
            prevCurNode->next=curNode->next;
            free(curNode);
            curNode=prevCurNode->next;
            count=1;
        }else{
            // 无需销毁curNode
            prevCurNode=curNode;
            curNode=curNode->next;
            count++;
        }
    }
    // 剩下的唯一一个结点就是留下的编号
    return curNode->val;
}

注:

(1)关于创建环形链表的返回值问题,由于要求的m为未知数,故对于每一个遍历的结点都需保留其前驱结点。创建环形链表完成后,由于是从phead开始计数,若返回phead,则导致无法定位其前驱结点,此种情况若m=1则会出错。故CreateCircle函数应该返回ptail而非phead;

(2)关于判定的截止条件:

由于只求最后一个留下的人的编号,故最后一轮时,整个环形链表只剩一个结点。可令循环结束条件为curNode->next == curNode;


http://www.kler.cn/a/522535.html

相关文章:

  • 【C++题解】1393. 与7无关的数?
  • 认识小程序的基本组成结构
  • C#高级:常用的扩展方法大全
  • python:洛伦兹变换
  • java小白日记32(注解)
  • 爬虫基础之爬取某基金网站+数据分析
  • 基于 Android 的日程管理系统的设计与实现
  • 状态码对照表
  • 蓝桥杯准备 【入门2】分支结构
  • STM32 EXTI中断配置
  • Lite.Ai.ToolKit - 一个轻量级的 C++ 工具包
  • labelimg闪退的解决办法
  • leetcode 2105. 给植物浇水 II
  • 【QT】- QUdpSocket
  • 2018年全国硕士研究生入学统一考试管理类专业学位联考英语(二)试题-解析版
  • 二十三种设计模式-桥接模式
  • 国内flutter环境部署(记录篇)
  • 【数据结构】_以SLTPushBack(尾插)为例理解单链表的二级指针传参
  • 每日一道算法题
  • 第05章 06 VTK标量算法中的Contouring算法
  • 【Linux网络编程】数据链路层
  • 计算机组成原理(2)王道学习笔记
  • 基于Flask的全国奶茶饮品加盟及门店数据分析系统的设计与实现
  • QT中给界面设置qss样式
  • 浅谈Linux 权限、压缩、进程与服务
  • 锐捷EWEB /auth 远程命令执行漏洞复现(附脚本)