js 排列 组合 的一个简单例子
最近工作项目需要用到js排列组合,于是就写了一个简单的demo。 前几天在网上找到一个写全排列A(n,n)的code感觉还可以,于是贴出来了,
排列的实现方式: 全排列主要用到的是递归和数组的插入 比如12的全排列,首先把1拿出来放到elementCur,再获取由1组成的数组[2],然后在循环把1插入到0,1的位置后再返回1,2][2,1] 如果是123那么首先获取23的全排列[2,3][3,2],然后在插入1,[1,2,3][2,1,3][2,3,1][1,3,2][3,1,2][3,2,1]
/*
全排列主要用到的是递归和数组的插入
比如12的全排列,首先把1拿出来放到elementCur,再获取由1组成的数组[2],然后在循环把1插入到0,1的位置后再返回1,2][2,1]
如果是123那么首先获取23的全排列[2,3][3,2],然后在插入1,[1,2,3][2,1,3][2,3,1][1,3,2][3,1,2][3,2,1]
*/
function permutate(array/*需要进行全排列的一维数组*/, permutatedArray/*存放返回结果*/) {
if (!permutatedArray) {
permutatedArray = [];
}
if (array.length > 1) {
//弹出第一个数
var elementCur = array.shift();
//排列剩余的数组
permutate(array, permutatedArray);
//返回剩余的数组的排列长度
var permutatedArrayLen = permutatedArray.length;
//第一个数与其他剩余数组所有数组组合
for (var j = 0; j < permutatedArrayLen; j++) {
//弹出不齐的组
var p = permutatedArray.shift();
//把当前元素放到排列好的数组的所有位置
for (var i = 0; i <= p.length; i++) {
//复制排列好的数组
var r = p.slice(0);
//插入数据到数组的位置
r.splice(i, 0, elementCur);
//保存
permutatedArray.push(r)
}
}
//退出条件
} else {
permutatedArray.push([array[0]]);
}
return permutatedArray;
}
那么我们需要一个组合C(m,n)的API,code如下,组合实现的原理非常简单,就是依次循环数组的元素,循环的嵌套层数是有m来决定的,内部的循环下标在外部的下标加1。所以用function来组装
/*
组合实现的原理非常简单,就是依次循环数组的元素,循环的嵌套层数是有m来决定的,内部的循环下标在外部的下标加1。所以用function来组装
*/
function combination(arr/*n需要组合的一维数组*/, num/*m需要取几个元素来组合*/, fun/*对组合后的元素的处理函数,如全排列permutate*/) {
/*这里假设num最大值为10 一般A(n,m)中的m应该不会太大 */
if (arr.length < num || num > 10)
{
return [];
}
var variable = ["a", "b", "c", "d", "e", "f", "g", "h", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u"];
var replaceStr = "#$#";
var str = " var arr=arguments[0]; var fun=arguments[1]; var ret=[]; for (var a = 0; a < arr.length; a++) { "+replaceStr+" } return ret;"
for (var i = 1; i < num; i++) {
str = str.replace(replaceStr, " for (var " + variable[i] + " =" + variable[i - 1] + "+ 1; " + variable[i] + " < arr.length; " + variable[i] + "++) { " + replaceStr + " }")
}
var temp = " var temp= []; ";
for (var i = 0; i < num; i++) {
temp += "temp.push(arr[" + variable[i] + "]); ";
}
if (fun) {
temp += " ret.push(fun(temp)); ";
}
else {
temp += " ret.push(temp); ";
}
str = str.replace(replaceStr, temp);
//console.log(str);
return (new Function(str)).apply(null, [arr, fun]);
}
那么我们一个普通的排列A(n,m)就很简单了。调用方式如下:
var a = combination([, , , , , ], , permutate);
for (var i = ; i < a.length; i++) {
for (var j = ; j < a[i].length; j++) {
console.log(a[i][j].join(''));
}
}
其实排列组合网上还有很多很好的精辟实现,比如以下code,个人已经加入了简单的原理描述:
/*
组合主要用到了循环加递归的方式 实现的,个人觉得很是精辟,
举例来说吧choose([1,2,3,4,5,6], 3)
第一次循环的时候 arr是[1,2,3,4,5,6],size=3,result=[],
经过一次递归后的结果是什么样的了?递归里面也有循环递归
经过第一次循环第一次递归变为arr=[3,4,5,6],size=1,result=[1,2],所以结果就出来了[1,2,3][1,2,4][1,2,5][1,2,6]
那么第一次循环第二次递归arr=[4,5,6],size=1,result=[1,3],所以结果就出来了[1,3,4][1,3,5][1,3,6]
那么第一次循环第三次递归arr=[5,6],size=1,result=[1,4],所以结果就出来了[1,4,5][1,4,6]
那么第一次循环第四次递归arr=[6],size=1,result=[1,5],所以结果就出来了[1,5,6]
那么第二次循环第一次递归变为arr=[4,5,6],size=1,result=[2,3],所以结果就出来了[2,3,4][2,3,5][2,3,6]
*/
function choose(arr, size) {
var allResult = [];
(function (arr, size, result) {
var arrLen = arr.length;
if (size > arrLen) {
return;
}
if (size == arrLen) {
allResult.push([].concat(result, arr))
} else {
for (var i = 0 ; i < arrLen; i++) {
var newResult = [].concat(result);
newResult.push(arr[i]); if (size == 1) {
allResult.push(newResult);
} else {
var newArr = [].concat(arr);
newArr.splice(0, i + 1);
arguments.callee(newArr, size - 1, newResult);
}
}
}
})(arr, size, []);
return allResult;
}
/*
这里的排列和组合一样 也是运用循环和递归的思想,比如arr=[1,2,3] ,size=3
第一次循环curItem=1 第一次递归newArr=3,result=[1,2] 所以结果是[1,2,3]
第一次循环curItem=1 第二次递归newArr=2,result=[1,3] 所以结果是[1,3,2]
第二次循环curItem=2 第一次递归newArr=3,result=[2,1] 所以结果是[2,1,3]
第二次循环curItem=2 第二次递归newArr=1,result=[2,3] 所以结果是[2,3,1]
*/
function queue(arr, size) {
if (size > arr.length) { return; }
var allResult = []; (function (arr, size, result) {
if (result.length == size) {
allResult.push(result);
} else {
for (var i = 0, len = arr.length; i < len; i++) {
var newArr = [].concat(arr),
curItem = newArr.splice(i, 1);
arguments.callee(newArr, size, [].concat(result, curItem));
}
}
})(arr, size, []); return allResult;
}
function showResult(result) {
console.log('The number of result sets: ' + result.length);
for (var i = 0, len = result.length; i < len; i++) {
console.log(result[i]);
}
} // showResult(choose([1, 2, 3, 4, 5, 6], 3));
showResult(queue([1, 2, 3], 3));
有不当的地方还请大家指正!
js 排列 组合 的一个简单例子的更多相关文章
- c++有关构造函数、析构函数和类的组合的一个简单例子
		
来源链接 实验四(下) 代码 #include <iostream> using namespace std; enum CPU_Rank {P1 = 1, P2, P3, P4, P5, ...
 - 一个简单例子:贫血模型or领域模型
		
转:一个简单例子:贫血模型or领域模型 贫血模型 我们首先用贫血模型来实现.所谓贫血模型就是模型对象之间存在完整的关联(可能存在多余的关联),但是对象除了get和set方外外几乎就没有其它的方法,整个 ...
 - (转)Java中使用正则表达式的一个简单例子及常用正则分享
		
转自:http://www.jb51.net/article/67724.htm 这篇文章主要介绍了Java中使用正则表达式的一个简单例子及常用正则分享,本文用一个验证Email的例子讲解JAVA中如 ...
 - C语言多线程的一个简单例子
		
多线程的一个简单例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...
 - quartz---的一个简单例子
		
quartz---的一个简单例子 首先建立一个maven项目.jar工程即可.(提示:我前面有如何建立一个maven工程的总结以及maven环境的配置.) 1.建立好后点击到app中运行,--> ...
 - 用node.js从零开始去写一个简单的爬虫
		
如果你不会Python语言,正好又是一个node.js小白,看完这篇文章之后,一定会觉得受益匪浅,感受到自己又新get到了一门技能,如何用node.js从零开始去写一个简单的爬虫,十分钟时间就能搞定, ...
 - 用socket.io实现websocket的一个简单例子
		
socket.io 是基于 webSocket 构建的跨浏览器的实时应用. 逛博客发现几个比较好的 一.用socket.io实现websocket的一个简单例子 http://biyeah.iteye ...
 - EXT JS认识EXTJS,第一个EXTJS例子
		
大部分内容转载自:http://blog.csdn.net/wanghuan203/article/details/8011112 和http://www.cnblogs.com/willick/p/ ...
 - ACM~排列组合&&hdu例子
		
排列组合是数学中的一个分支.在计算机编程方面也有非常多的应用,主要有排列公式和组合公式.错排公式.母函数.Catalan Number(卡特兰数)等. 一.有关组合数学的公式 1.排列公式 P(n ...
 
随机推荐
- document.referrer 特性
			
最近需要用到document.referrer,但是在测试的时候,总是获取为空,百思不得其解. 于是发动百度,看了大量的文章没有一个说到点子上是为什么,后来偶然看到document.referrer ...
 - C#字段中加入list<类字段> 的两种写法
			
类1 public class NumCon { public string zsNum { get; set; } } 类2 public class RepeatMess //重复数据响应 { p ...
 - Spring+Struts2/Hibernate 学习笔记
			
============Spring与Struts2整合============ (1)拷JAR包(Spring.Struts2) (2)配置org.springframework.web.conte ...
 - Spring JDBC 访问MSSQL
			
在Spring中对底层的JDBC做了浅层的封装即JdbcTemplate,在访问数据库的DAO层完全可以使用JdbcTemplate完成任何数据访问的操作,接下来我们重点说说Spring JDBC对S ...
 - img图片放大控件 lightbox.js
			
1.引入相关js,css jquery-1.7.2.min.js,lightbox.css,lightbox.js 2 图片增加<a href="大图片地址" rel=& ...
 - (转)四种常见的 POST 提交数据方式
			
四种常见的 POST 提交数据方式(转自:https://imququ.com/post/four-ways-to-post-data-in-http.html) HTTP/1.1 协议规定的 HTT ...
 - MySQL设置字符集CHARACTER SET
			
本文地址:http://www.cnblogs.com/yhLinux/p/4036506.html 在 my.cnf 配置文件中设置相关选项,改变为相应的character set. 设置数据库编码 ...
 - MVVM了解
			
了解WPF要有两年,零零碎碎也做了几个项目,之前面试的时候面试官必问对MVVM的了解. 其实不太了解,只是做项目的时候一直采用这种模式,Model-View-ViewModel.以下是我在了解过程中的 ...
 - (译)如何优化cocos2d程序的内存使用和程序大小:第二部分(完)
			
前言:从上周发布教程的微博反应情况来看,cocos2der们对于游戏的内存问题还是非常关心的.本文是上一篇博文的续,旨在教大家如何减少cocos2d程序的大小. 全文如下: 减少你的程序的大小 把纹理 ...
 - linux-3重置root密码
			
1.首先确认是redhat7 [root@localhost /]# cat /etc/redhat-release 详细步骤: 第1步:开机后在内核上敲击"e". 第2步:在li ...