跳至主要內容

圆圈中最后剩下的数 约瑟夫问题

微信公众号:储凡2023/2/11大约 5 分钟

圆圈中最后剩下的数 约瑟夫问题

题目链接

题目描述

把n个人的编号改为0~n-1,然后对删除的过程进行分析。 第一个删除的数字是(m-1)%n,几位k,则剩余的编号为(0,1,...,k-1,k+1,...,n-1),下次开始删除时,顺序为(k+1,...,n-1,0,1,...k-1)。 用f(n,m)表示从(0~n-1)开始删除后的最终结果。 用q(n-1,m)表示从(k+1,...,n-1,0,1,...k-1)开始删除后的最终结果。 则f(n,m)=q(n-1,m)。

下面把(k+1,...,n-1,0,1,...k-1)转换为(0~n-2)的形式,即 k+1对应0 k+2对于1 ... k-1对应n-2 转化函数设为p(x)=(x-k-1)%n, p(x)的逆函数为p^(x)=(x+k+1)%n。 则f(n,m)=q(n-1,m)=p^(f(n-1,m))=(f(n-1,m)+k+1)%n,又因为k=(m-1)%n。 取余 f(n,m)=(f(n-1,m)+m)%n;

最终的递推关系式为 f(1,m) = 0; (n=1) f(n,m)=(f(n-1,m)+m)%n; (n>1)

刷题思路

代码实现

/**
 * 【中等】圆圈中最后剩下的数 约瑟夫问题
 */

// 把n个人的编号改为0~n-1,然后对删除的过程进行分析。
// 第一个删除的数字是(m-1)%n,几位k,则剩余的编号为(0,1,...,k-1,k+1,...,n-1),下次开始删除时,顺序为(k+1,...,n-1,0,1,...k-1)。
// 用f(n,m)表示从(0~n-1)开始删除后的最终结果。
// 用q(n-1,m)表示从(k+1,...,n-1,0,1,...k-1)开始删除后的最终结果。
// 则f(n,m)=q(n-1,m)。

// 下面把(k+1,...,n-1,0,1,...k-1)转换为(0~n-2)的形式,即
// k+1对应0
// k+2对于1
// ...
// k-1对应n-2
// 转化函数设为p(x)=(x-k-1)%n, p(x)的逆函数为p^(x)=(x+k+1)%n。
// 则f(n,m)=q(n-1,m)=p^(f(n-1,m))=(f(n-1,m)+k+1)%n,又因为k=(m-1)%n。
// 取余
// f(n,m)=(f(n-1,m)+m)%n;

// 最终的递推关系式为
// f(1,m) = 0;                        (n=1)
// f(n,m)=(f(n-1,m)+m)%n; (n>1)

/**
 * 递归实现
 */
export function LastRemainingSolution(n, m) {
  // 递推公式: f(0)=-1  f(1)=0 f(i)={f(i-1)+m}%i

  if (n === 0) {
    return -1
  }

  if (n === 1) {
    return 0
  }

  // 递归
  return (LastRemainingSolution(n - 1, m) + m) % n
}

/**
 * 非递归实现
 */
export function LastRemainingSSolution01(n, m) {
  // 当然,这里也可以添加上负数的校验情况
  if (n === 0) {
    return -1
  }

  if (n === 1) {
    return 0
  }

  // 循环处理
  let result = 0
  for (let index = 2; index <= n; index++) {
    // f(n,m)=[f(n-1,m)+m]%n
    result = (result + m) % index
  }
  // 返回
  return result
}
/*
 * @Description: 【中等】圆圈中最后剩下的数 约瑟夫问题
 * @Version: Beta1.0
 * @Author: 微信公众号:储凡
 * @Date: 2021-05-05 14:48:28
 * @LastEditors: 微信公众号:储凡
 * @LastEditTime: 2021-05-05 15:11:02
 */

function LastRemainingSolution(n, m) {
  // 递推公式: f(0)=-1  f(1)=0 f(i)={f(i-1)+m}%i

  if (n === 0) {
    return -1
  }

  if (n === 1) {
    return 0
  }

  // 递归
  return (LastRemainingSolution(n - 1, m) + m) % n
}

// 非递归实现
function LastRemainingSSolution01(n, m) {
  // 当然,这里也可以添加上负数的校验情况
  if (n === 0) {
    return -1
  }

  if (n === 1) {
    return 0
  }

  // 循环处理
  let result = 0
  for (let index = 2; index <= n; index++) {
    // f(n,m)=[f(n-1,m)+m]%n
    result = (result + m) % index
  }
  // 返回
  return result
}

一些建议

更新日志

2024/7/29 15:43
查看所有更新日志
  • 5a2b2-feat: 移除markdown-cli模块,采用prettier校验文档格式
  • a3cca-refactor: 替换eslint规则,使用antfu/eslint模块 (#138)
  • c0f2d-refactor: 升级vuepress相关版本,优化项目结构 (#137)
  • 6ff0a-feat(algo): 新增剑指、shell等算法文档
  • 06596-feat: 算法相关文档新增固定链接,优化导入代码配置
  • 9b9e4-feat: 算法相关文档更新,删除讨论链接 (#88)
  • b0275-feat(markdownlint-cli): 添加markdown文档校验,支持lint脚本自动格式化文档
  • 5f1e1-feat: 导航栏、侧边栏内容修改,新增目录对应的文档
  • 2b8a3-docs: 新增一些文档,优化项目结构
  • 02ab1-style: 文档目录调整,修改mdEnhance配置
  • 8de1a-feat: 剑指算法文档更新,修改目录结构
  • afe76-docs: 新增一些算法解析文档
  • ced18-docs: 更新一些文档,优化导航栏
  • a23ce-refactor: 新增manuscript目录,优化文稿结构
  • e34c0-style(code): 代码风格eslint格式化,新增部分文档
  • 74aa9-docs(algorithm): 新增一些文档
  • 3c22c-refactor: 新增Eslint配置,修改相关代码风格
  • 9bbe9-feat: 修改导航栏结构,添加文档
  • e4c74-feat: 新增算法源码
贡献者: chu fan,Chu Fan,chufan,142vip.cn,chufan443