点击注册
点击注册
.

棋牌百科 如何用Matlab实现存在重复元素的向量不重复的所有排列


发布日期:2022-03-05 23:24    点击次数:140


这个题目还是挺有意思的。首先,我们可以计算所有不重复排列的数目。比如长度为5的数组[0,0,1,2,2],存在三种不同的元素{0,1,2},每种元素出现的次数为2,1,2。则所有不重复排列的个数为 。我一开始的想法是,用rangperm生成随机组合,然后去重,直到去重后的数量等于所有不重复的排列的数目,后来发现在向量长度大于10时效率实在太低。这种方法的代码是这样的。(代码具体思路就不写了,下面这个例子大概要12分钟出结果)a = int8([1,2,3,3,3,4,4,4,4,5,5,5,5,5]); % 计算不重复排列的总数目 aNum = length(a); c = unique(a); aElemNum = sum(bsxfun(@eq,a',c)); aPermsTotal = factorial(length(a))/prod(factorial(aElemNum)); re = zeros(0,length(a),'int8'); tmp = zeros(floor(aPermsTotal*0.01),length(a),'int8'); while true for ii = 1:aPermsTotal*0.01 tmp(ii,:) = randperm(length(a),length(a)); end re = union(re,a(tmp),'row'); if (size(re,1)>=aPermsTotal) break; end end后来我就想去看看MATLAB的perms函数的实现方式,调用edit命令就能看到源代码。edit perms发现这个perms函数并不是built-in函数,代码思路就是递归(但这个递归被改写为了循环)。只需要稍微改一下,在每次递归结尾判断去重即可。完整代码如下。(我为了方便理解,写成了调用递归函数的形式。)function C = permsr(v) n = length(v); if n == 1 C = v; else Psmall = permsr0(v(1:end-1)); m = size(Psmall,1); P = zeros(n*m,n,class(v)); P(1:m, end) = v(end); P(1:m, 1:end-1) = Psmall; for j = n-1:-1:1 reorder = [1:j-1, j+1:n]; P((n-j)*m+1:(n-j+1)*m,j) = v(end); P((n-j)*m+1:(n-j+1)*m,reorder) = Psmall; end C = unique(P,'rows'); end end同样是a = [1,2,3,3,3,4,4,4,4,5,5,5,5,5]这个例子,大概5秒钟即可得出结果。结果是一个5045040×14的矩阵,说明有超过500万种不同的排列。a = int8([1,2,3,3,3,4,4,4,4,5,5,5,5,5]); p = permsr(a); size(p) % ans = 5045040 14测试一下,与上面方法得出的re相比,有没有不同的排列。setdiff(p,re,'rows'); % ans = 空的 0×14 int8 矩阵 setdiff(re,p,'rows'); % ans = 空的 0×14 int8 矩阵re与p行向量之间的差集均为0,表示二者是相等的,验证了我们的结果。

繁忙的工作和学习之余体验游戏是比较好,适当的玩游戏可以让自身承受的压力缓解。在现实生活中也是可以就四人麻将体验,与亲朋好友一起打发无聊时间,从游戏中来进行交流。可以说的是和家人朋友一起玩游戏是很美好的事情,人们也都是会喜欢这样的方式。

内蒙古麻将选庄规则:第一盘随机选庄,第二盘开始谁胡谁坐庄棋牌百科,牌抓完没人胡就荒庄,荒庄则连庄。如果一炮多响,下盘由放炮者坐庄。