NC132 环形链表的约瑟夫问题

NC132 环形链表的约瑟夫问题

单向循环链表+模拟

  • 尾插法建立单向链表,节点的val为自己的编号
  • 最后将尾节点的 next 指向头结点,形成单向循环列表
  • 进行循环操作,循环结束的条件为链表中只剩下一个元素,也就是 p.next === p
  • count 用于计数,初始化为1;p为当前节点,初始化从head开始;pre为p的前一个节点,初始化为rear;
  • 如果当前计数达到 m ,表明p需要被删除,让 pre.next = p.next 即可,p后移一位
  • 如果不需要删除,count + 1,pre,p都后移一位
  • 最终循环结束,循环链表中只剩下一个p,返回 p.val 也就是这个节点的编号
/**
 * 
 * @param n int整型 
 * @param m int整型 
 * @return int整型
 */
function Node(x){
    this.val = x
    this.next = null
}
function ysf( n ,  m ) {
    if(n === 1) return 1
    // 单向循环列表
    let head = new Node(1)
    let rear = head
    for(let i = 2; i <= n ; i++){
        let node = new Node(i)
        rear.next = node
        rear = node
    }
    rear.next = head
    let count = 1
    let p = head
    let pre = rear
    // 当链表中有大于两个节点的时候
    while(p.next !== p){
        // 当前节点需要被删除
        if(count === m){
            pre.next = p.next
            p = p.next
            count = 1
        }else{
            count ++
            pre = p
            p = p.next
        }
    }
    return p.val
}
module.exports = {
    ysf : ysf
};

数学

看了题解发现可以使用数学方法来解答,通过寻找其中的规律来解答

  • f(n,m) 表示有n个人,报m出局
  • f(1,m) 一个人的话最终留下的编号为0(从0开始计数)
  • f(2,m) 需要以前一轮结束的位置开始再进行一轮,结果也就是留下 ( f(1,m) + m ) % 2
  • ...
  • f(n,m) = ( f(n - 1 , m) + m ) % n
  • 所以只需要根据这样的规律推出f(n,m)就可以了
/**
 * 
 * @param n int整型 
 * @param m int整型 
 * @return int整型
 */
function Node(x){
    this.val = x
    this.next = null
}
function ysf( n ,  m ) {
    if(n === 1) return 1
    let res = 0
    for(let i = 2; i <= n; i ++){
        res = (res + m) % i
    }
    //题目要求编号从 1 开始,所以这里加上1
    return res + 1
}
module.exports = {
    ysf : ysf
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值