牛客-环形链表的约瑟夫问题

目录

题目

描述

示例1

示例2

图解

代码(解析在注释中)


题目

描述

编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。

下一个人继续从 1 开始报数。

n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?

数据范围: 1≤�,�≤100001≤n,m≤10000

进阶:空间复杂度 �(1)O(1),时间复杂度 �(�)O(n)

示例1

输入:
5,2     
返回值:
3    
说明:
开始5个人 1,2,3,4,5 ,从1开始报数,1->1,2->2编号为2的人离开
1,3,4,5,从3开始报数,3->1,4->2编号为4的人离开
1,3,5,从5开始报数,5->1,1->2编号为1的人离开
3,5,从3开始报数,3->1,5->2编号为5的人离开
最后留下人的编号是3      

示例2

1,1
1

图解

代码(解析在注释中)

/**
 * 定义一个结构体 ListNode,用于表示链表节点
 */
typedef struct ListNode ListNode;

/**
 * 创建一个新的链表节点,并将其值初始化为给定整数 x。
 *
 * @param x 初始化节点值的整数
 * @return 新创建的 ListNode 类型指针
 */
ListNode* New_node(int x) {
    ListNode* node = (ListNode*)malloc(sizeof(ListNode)); // 分配内存空间
    if (node == NULL) { // 检查内存分配是否成功
        exit(1); // 若失败则退出程序
    }
    node->next = NULL; // 初始化 next 指针为空
    node->val = x; // 设置节点值
    return node; // 返回新创建的节点指针
}

/**
 * 根据给定整数 n 创建一个包含 n 个节点的环形链表,
 * 节点值从 1 到 n 依次递增。
 *
 * @param n 链表中节点的数量(整数)
 * @return 环形链表的尾节点指针
 */
ListNode* Link(int n) {
    ListNode* head = New_node(1); // 创建头节点
    ListNode* tail = head;

    // 循环创建并连接后续节点
    for (int i = 2; i <= n; i++) {
        tail->next = New_node(i);
        tail = tail->next;
    }

    // 将尾节点与头节点相连形成环形链表
    tail->next = head;
    return tail;
}

/**
 * 删除环形链表中每 m 个节点中的倒数第二个节点,直到只剩下一个节点为止。
 * 最后返回该单个节点的值。
 *
 * @param n 环形链表中原始节点的数量(整数)
 * @param m 每隔几个节点删除一次倒数第二个节点(整数)
 * @return 剩余单个节点的值(整数)
 */
int ysf(int n, int m) {
    ListNode* prev = Link(n); // 创建并初始化环形链表
    ListNode* pcur = prev->next;
    int count = 1;

    // 遍历链表,直到只剩下一个节点
    while (pcur->next != pcur) {
        if (count == m) {
            prev->next = pcur->next; // 删除倒数第二个节点
            free(pcur);
            pcur = prev->next; // 更新 pcur 指向下一个有效节点
            count = 1;
        } else {
            prev = pcur;
            pcur = pcur->next;
            count++;
        }
    }

    // 销毁最后一个节点前获取其值
    int var = prev->val;

    // 释放最后一个节点内存
    free(prev);
    prev = NULL;

    return var; // 返回最后一个节点的值
}

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

普通young man

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

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

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

打赏作者

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

抵扣说明:

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

余额充值