[Daily Practice] -约瑟夫环问题

问题描述

0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
该题目来源于leetcode,点击进入

读题

例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

解法一

比较直观的解法

public int lastRemaining(int n, int m) {
        LinkedList<Integer> list = new LinkedList<>();
        // 全部加进去
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        // 只要链表长度不为 1,就不断循环
        while (list.size() != 1) {
            for (int i = 0; i < m; i++) {
            	// 取出第一个元素并删除
                Integer pre = list.pollFirst();
                if (i != m - 1) {
                	// 如果不是第m个,就加到末尾
                    list.add(pre);
                }
            }
        }
        return list.pollFirst();
}

解法二

首先,我们设定n个数值中不断删除m位,最后得到的值为f(n,m)
第一次删掉的数字为(m-1)%n 记做x
那么剩下的n-1个数字就变成了(此处假设n大于2)

01x-1x+1n-1

因为需要从被删掉的数字后面一位重新计数,我们把X+1放到首位,从新排列后的数字顺序为

原始数组对应顺序位置
x+10
x+21
n-1n-x-2
0n-x-1
x-1n-2

为什么0对应的位置是n-x-1?
我们第一步的时候删除了一个数字,可以理解成把这个链表分成了两部分,
第一部分的长度为x(因为是从0开始的),
那么第二部分的长度就为 n-x-1
现在把第一部分拼接到第二部分的后面,
那么第一分部的第一个数,也就是0,就变成了n-x-1+1个数字,也就是n-x个数字,因为是从0开始的,所以对应的就是n-x-1
关键点:
假设对应的顺序位置为A,原始数值为B
那么顺序位置A与数值B的关系我们可以得出公式:

B = (A+x+1) mod n

由最初的定义可以得到:
n-1个数字中不断删除第m个,最后得到的值为f(n-1,m)
从我们上面的公式可以反推回它的值为(f(n-1,m)+x+1)%n
这个值也就是我们开始定义的f(n-1,m)
x=(m-1)%n代入简化可得:

f(n,m)=f(n−1,m)+m) mod n,且f(1,m) = 0

代码实现

 public static int lastRemaining(int n, int m) {
        return n == 1 ? 0 : (lastRemaining(n-1,m) + m) % n;
    }

或者

public int lastRemaining(int n, int m) {
    int flag = 0;   
    for (int i = 2; i <= n; i++) {
        flag = (flag + m) % i;
    }
    return flag;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值