1 | clear all |
注意:该文章是在2014年所写,代码中的wavplay函数在matlab2014之后的版本被移除,需要自己下载该函数文件,详情见https://ww2.mathworks.cn/matlabcentral/fileexchange/71798-wavplay?s_tid=srchtitle
1 | clear all |
注意:该文章是在2014年所写,代码中的wavplay函数在matlab2014之后的版本被移除,需要自己下载该函数文件,详情见https://ww2.mathworks.cn/matlabcentral/fileexchange/71798-wavplay?s_tid=srchtitle
前一篇文章用人、狗、鸡、米过河问题介绍了解决过河问题的普适解决方法以及其改进算法。本文先用该算法解决我们常见的六只老虎过河问题,然后用特殊方法解决另外一种过河问题。
今天偶尔想到了过河问题。记得读小学六年级的时候第一次接触到这个问题—六个老虎过河问题(百度上有详细介绍,本文解决的是一个简单的问题,下一篇文章中将讨论该问题),当时都是从逻辑思维的方法得到正确的解决方法。本文介绍了普遍适用该类问题的方法以及该方法的改进方法,下一篇文章将介绍问题的变型及解法。
问题:如何将一个数组循环左移或者右移k位?
在下面的解决方案中,我们以循环左移为例。 我们最容易想到的是,将前k个元素复制到一个临时的数组中,然后将剩下的n-k个元素向左移动k个位置,然后将之前的k个元素复制到剩下的位置。这种方法使用了k个额外的存储空间。我们想到到另一种方法是,只借助一个临时空间,每次只向左移动1位,循环k次。这种方法产生了多于的运行时间。前面一篇文章中用程序实现了循环右移一个数组的算法。前面提到的都是比较常规的算法,下面从其它角度来考虑这一问题:
仅用一个辅助节点将一个大小为n数组循环右移k位的三种办法:
1、时间复杂度最大:将所有元素每次只移动一位,总共移动k次,程序实现十分容易,在此就不具体实现了。
2、时间复杂度适中:依次将每个元素都放到辅助节点上,然后将其储存到目的节点,具体程序如下:
前一篇文章中,我们在Java中用实现两种不同接口的类,解决了不重复选择随机数的问题。现在我们在C++中,通过几种不同的算法来解决上述问题。在下面的四种算法实现中,用的随机函数都是C的库函数,这个函数产生的随机数的范围是限定的,[0, 32767]。当然我们可以通过四则运算来改变取值范围。具体的算法实现如下:
随机数的不重复选择就是从$n$个数中随机选取$m(m<n)$个数。在本文中,我们用Java来实现。因此我们先介绍Java的相关知识。
在Java中,Java.util.Set接口和Java.util.List接口一样,都是继承自Java.util.Collection接口。但是两者有不同的特点:
List接口:一种能包含重复元素的有序集合,具体实现该接口的类有:Vector、Stack、ArrayList、LinkedList等等.
Set接口:一种不包含重复元素的集合,常见的实现该接口的类有:HashSet、LinkedHashSet、TreeSet。
在上一篇文章中,我们实现了c语言中的大整数的运算,并且用Miller-Rabin算法实现了对大素数的测试。本来我准备用Java代码实现大整数的运算,查了一下资料发现Java中java.math的BigInteger可以实现大整数的表示和计算。BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
基本原理:
费尔马小定理:如果$p$是一个素数,且$0<a<p$,则$a^{(p-1)}\%p=1$.
利用费尔马小定理,对于给定的整数$n$,可以设计素数判定算法,通过计算$d=a^{(n-1)}\%n$来判断$n$的素性,当$d!=1$时,$n$肯定不是素数,当$d=1$时,$n$ 很可能是素数.
二次探测定理:如果$p$是一个素数,且$0<x<p$,则方程$x^2\%p=1$的解为:$x=1$或$x=p-1$.
利用二次探测定理,可以再利用费尔马小定理计算$a^{(n-1)}\%n$的过程中增加对整数$n$的二次探测,一旦发现违背二次探测条件,即得出$n$不是素数的结论.