现在的位置: 首页 > 综合 > 正文

带有限制条件的数字排列

2013年10月28日 ⁄ 综合 ⁄ 共 2033字 ⁄ 字号 评论关闭
比如打印出 1,2,2,3,4,5 这六个数字的所有排列,其中3不能在第三位上,4和5不能相连 (一共为198个)
计算公式:
A = 6 * 5 * 4 * 3 * 2 / 2 (所有的全排列)
B = 5 * 4 * 3 * 2 /2 (第3位为3的所有排列)
C = 4 *3 * 2 * 5 * 2 / 2 (45相连的所有排列)
D = 4 * 3 * 2 * 2 / 2 - 3 * 2 * 2 / 2( 第3位为3并且45相连的所有排列(B交C))
formula = A - B - C + D

= 6 * 5 * 4 * 3 * 2 / 2 - 5 * 4 * 3 * 2 /2 - 4 *3 * 2 * 5 * 2 / 2 + (4 * 3 * 2 * 2 / 2 - 3 * 2 * 2 / 2 )
= 6 * 5 * 4 * 3 - 5 * 4 * 3 - 4 *3 * 2 * 5 + 18
= 5 * 4 * 3 * 3 + 18

= 180 + 18
= 198
1.可以按照初中教材排列组合的原理;
第一位有6种选择
第二位有5种选择
...
...
第6位有1种选择。
但是2重复了两次,所以这种方法需要改进下了
我们不妨这样定义一个数组 a=[1,2,1,1,1]
a[0] = 1代表 ‘1’这个要排列的数字有一个
a[1] = 2代表 ‘2’这个要排列的数字有两个
...
...
a[4] = 1代表 ‘5’这个要排列的数字有一个,
每次排列一个数字以后,a相应位置上的值要减一,
如果该位置上的值为0,表示所对应的数字已经出现在排列中了,不能够再进行排列
附上朋友的一段代码:

function mainChange(a, b, c, times) {
for (var i = 0; i < 5; i++) {
var a1 = a.slice(0);
var b1 = b.slice(0);
var c1 = c.slice(0);
if (!c1[i] || (times == 3 && a1[i] == 3) || (times != 1 && b1[times - 2] == 4 && a1[i] == 5) || (times != 1 && b1[times - 2] == 5 && a1[i] == 4)) continue;
b1.push(a1[i]);
c1[i]--;
if (times != 6) {
mainChange(a1, b1, c1, times + 1);
} else {
//console.log(b1.join(""));
document.write('<span style="display:inline-block; margin:10px; padding:0px 10px; border:solid 1px #cdcdcd">' + b1.join("") + '</span>');
}
}
}
mainChange([1, 2, 3, 4, 5], [], [1, 2, 1, 1, 1], 1);
2.按照插入的方法解决
先把2,2做为初始排列,
再插入1, 这样就会出现3种结果:
1,2,2 2,1,2 2,2,1
再把3插入,结果有12个:
3,1,2,2 1,3,2,2 1,2,3,2 ... ... 2,2,1,3
一次类推,
这里要处理好限制条件,
这种插入方法的限制还是很大的,比如多个数字都出现重复的情况,应该有更通用的插入方法,待优化
附上javascript代码

<script>
var line = '22';
var pool = [1,3,4,5];
var join45 = /(45)|(54)/; //判断4和5是否相连
(function(){
insertNew(line,pool[0]);
})();
//插入新的数据
function insertNew(li ,elem){
var l = li.length;
var k;
for(k = 0; k < l + 1; k ++){
var piece = arrange(li,elem,k);
if(piece.length >= 6){
var third = piece.substring(2,3); // 拿到中间的数字
var j45 = piece.match(join45);
//中间数为3 或者 4和5相连
if(third == '3' || j45 != null){
continue;
}
document.write('<span class="shop">' + piece + '</span>');
}else{
insertNew(piece ,pool[piece.length - 2]);
}
}
}
//把elem插入到指定位置pos
function arrange(line,elem,pos){
var str = line.toString();
var strLen = line.length;
var front = str.substring(0,pos); //这里建议使用slice
var back = str.substring(pos,strLen);
var newArr = assemble(front,elem,back);
return newArr;
}
//a,b,c三个字符串组合起来
function assemble(a,b,c){
var str = a + b + c;
var sl = str.length;
return str;
}

</script>
3.交换位置的排列方法, (比以上效率 暂都要高的方法,时已经忘掉原理了,还需要看下组合学)
4.效率更高的交换位置排列方法,(这个得差资料了,嘿嘿,从组合学中获得的蛛丝马迹)

抱歉!评论已关闭.