剑指Offer解题报告(Java版)——约瑟夫环 45

?
?

引言

?
?

常见的约瑟夫环问题有用循环链表做的,有用数组做的,这里提供一个用数学公式做的,由此可见,很多计算机的问题如果最终用到数学的知识,时间复杂度会大大的降低

?
?

分析问题

?
?

首先我们对0到n-1删除第一个数进行分析,第一个被删除的数一定是序号为m-1的数,因为0号数了1,1号数了2,m-1号数了m,那么应该删掉m-1号,设m-1号是第k号,这里这样做是因为后面可以扩展,想扩展为m-1%n=k

?
?

剩下的数按照序列重排序如下

?
?

因为删掉的是k,那么下面第一个就是k+1了,这个很好理解

?
?

假设我们设f函数的输出是原来的在n个数中,每次数m下,最后留下的数

?
?

而现在删掉了k,只有n-1个数了,每次数m下,最后留下的数是f‘(n-1,m)

?
?

?
?

如何建立f和f‘之间的关系呢

?
?

我们对重排序之后的数做一个映射

?
?

?
?

该映射为

p(x) -- > y ::: y=(x-k-1)%n

?
?

则映射完之后就跟原来的问题一样了,也就是f(n-1,m)了

?
?

也就是p(f‘(n-1,m)=f(n-1,m)

?
?

而我们现在只有f(n,m)和f‘(n-1,m)之间的关系

?
?

所以我们还需要再转换一下,也就求映射的逆

?
?

?
?

而映射p的逆映射为

?
?

o(y) -- >x x=(y+k+1)%n

?
?

其中k可以替换 k%n=(m-1)%n

?
?

即o(y) -- >x x=(y+m)%n

?
?

对应到之前f(n-1,m)和f‘(n-1,m)之间的关系

?
?

f‘(n-1,m)=f(n-1,m)+m%n

?
?

?
?

f(n,m)=f‘(n-1,m)

?
?

这样我们有f(n,m)和f‘(n-1,m)之间的关系,也有f(n-1,m)和f‘(n-1,m)之间的关系

?
?

带入之前的式子推到得到

?
?

?
?

解决问题

?
?

static int lastRemain(int n, int m) {

int last = 0;

if (n < 1 || m < 1) {

return -1;

}

for (int i = 2; i <= n; i++)

last = (last + m) % i;

return last;

}

?
?

时间: 2024-08-08 21:55:25

剑指Offer解题报告(Java版)——约瑟夫环 45的相关文章

剑指Offer解题报告(Java版)——排序数组中某个数的个数 38

? ? 分析问题 ? ? 问题只需要找到排序数组中某个数K的个数,由于已经是排序了,K一定是在一堆的,所以我们只需要找到第一个K的index1,然后找到最后一个K的index2就可以了 ? ? 而寻找K的过程我们一般通过二分法查找,这样时间复杂度能降到logn ? ? 解决问题 ? ? 我们通过二分法寻找k,如果中间的数小于k,那么在前半段找k:如果中间的数大于k,那么在后半段找k,那么如何判断找到的k是否是一堆k的边界呢 ? ? 找第一个k的时候判断方式如下: 如果中间的数等于k,那么先判断前

剑指Offer解题报告(Java版)——字符串转换为数字 49

? ? 引言 ? ? STOI是很常见的一道题,leetcode上也有,字符串转换为数字一般都会有现成的函数去实现这样的功能,但有时候需要我们理解其中的具体实现,因为虽然是个很常见的问题,但实际上需要考虑的问题还是很多的,尤其是corner case的处理,而这类问题一般要考虑两点:一点是符号,另外一点是越界 ? ? 分析问题 ? ? 如果字符串前面有空格怎么办,一般来说中间是没有空格的,但是前后可能有空格,所以我们首先需要去掉多余的空格字符,用到trim函数 ? ? 然后就是字符串中有可能第一

剑指Offer解题报告(Java版)——不用加减乘除做加法 47

? ? 引言 ? ? 一般这种不能用四则运算的题都只有用位运算来做,目的是加强大家对计算机计算的理解,真是有点扯淡呢 ? ? 解决问题 ? ? 首先我们得思考计算机是怎样做加法的呢,比如3加4,如果转换成二进制是0011和0100,加起来是7,也就是0111,相当于是两个二进制的异或运算 ? ? 但是我们再举一个例子就是4加4,会发现,两个二进制是0100和0100,异或运算的话结果为0000,但是我们想要的是1000,这是因为异或运算没有考虑到进位的问题,看来我们还要用一个运算去考虑进位的问题

剑指Offer解题报告(Java版)——扑克牌顺子 44

? ? 分析问题 ? ? 这个题目的关键点在于大小王可以看作任意的数字,那么我们就把这个任意的数字看作0也未尝不可,因为扑克牌中1-15都有数字,所以可以用0代表大小王 ? ? 这样我们就将问题转换成了从0-15中抽5个数字,看是否连续的问题,由于0可以看作任意数字,所以我们可以用0去补那些空缺的数,比如0,1,3也算是连续的 ? ? 要记住关键点还是这个任意数字上,考虑一个问题,就是如果这5个数中0的个数大于等于空缺数,那么坑一定能补上,所以一定是连续的,如果0的个数小于空缺数,那么0的个数不

剑指Offer解题报告(Java版)——n个骰子的点数 43

问题 ? ? n个骰子朝上的数之和为s,求s的所有可能以及概率 ? ? 分析问题 ? ? 如果是用笨方法,一般人最开始都会想到笨方法,那就是枚举法 ? ? 举个例子,比如两个骰子,第一个骰子的结果为1,2,3,4,5,6,两个骰子的结果是2,3,4,5,6,7:3,4,5,6,7,8:4,5,6,7,8,9:--7,8,9,10,11,12,共三十六种,用n平方size的数组记录这36个结果 ? ? 仔细分析可以发现其实这其中有很多是重复的,所以去除重复,考虑最小的应该是2,也就是n,最大的应该

剑指offer编程题Java实现——面试题7相关题用两个队列实现一个栈

剑指offer面试题7相关题目:用两个队列实现一个栈 解题思路:根据栈的先入后出和队列的先入先出的特点1.在push的时候,把元素向非空的队列内添加2.在pop的时候,把不为空的队列中的size()-1份元素poll出来,添加到另为一个为空的队列中,再把队列中最后的元素poll出来两个队列在栈不为空的情况下始终是有一个为空,另一个不为空的.push添加元素到非空的队列中,pop把非空队列的元素转移到另一个空的队列中,直到剩下最后一个元素,这个元素就是要出栈的元素(最后添加到队列中的元素). 1

剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具体的计算中,还是要将字符串转化成字符数组来进行计算. 实现两个大数的加法,要考虑到两个问题,两个数的和的位数问题,以及如何处理两个数按位相加产生的进位问题.首先两个整数相加,两个数的和的位数最多比最大的整数的位数多1:这样和的位数就确定了.对于进位问题,我的做法是先进行按位相加,相加操作完成后再按照

剑指offer编程题Java实现——面试题14调整数组顺序使奇数位于偶数之前

题目: 输入一个整数数组,实现一个函数来调整该数组中数组的顺序,使得所有的奇数位于数组的前半部分,偶数位于数组的后半部分. 解题思路:数组中维护两个指针,第一个指针初始化时候指向数组头部,第二个指针初始化时候指向数组尾部,第一个指针指向的数字总是偶数,第二个指针指向的数字总是奇数,如果第一个指针在第二个指针之前,则交换两指针指向的元素. 1 package Solution; 2 3 /** 4 * 剑指offer面试题14:调整数组顺序是奇数位于偶数前面 5 * 题目:输入一个整数数组,实现一

剑指offer编程题Java实现——面试题10二进制中1的个数

题目: 请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数.例如,把9表示成二进制是1001,有2位是1,该函数输出2解法:把整数减一和原来的数做与运算,会把该整数二进制表示中的最低位的1变成0,与运算进行多少次就有多少个1. 1 package Solution; 2 /** 3 * 剑指offer面试题10:二进制中1的个数 4 * 题目:请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数. 5 * 例如,把9表示成二进制是1001,有2位是1,该函数输出2 6 * 解法