全排列算法的JS实现

问题描述:给定一个字符串,输出该字符串所有排列的可能。如输入“abc”,输出“abc,acb,bca,bac,cab,cba”。

虽然原理很简单,然而我还是折腾了好一会才实现这个算法……这里主要记录的是解决问题中的思路。

我实现的是最普通的递归算法,也没有除重,嗯非递归及除重的算法以后再补上吧。

好了正文开始:

首先明确函数的输入和输出,输入是一个字符串,输出么对于JS而言用数组来表示最恰当了,所以函数的雏形应该是这样的:

function permutate(str) {
    var result = [];

    return result;
}

然后,确定是用递归的形式解决。递归的解法么,其实就是数学归纳法的寻找规律那一步。数学归纳法是什么样来着:第一步,给出基础值,比如输入为1的时候输出应该是成立的。第二步,假设对于输入n成立,证明输入n+1时也成立。

好了,所以先来完成第一步。对这个问题而言,基础情况应该是输入字符串为单个字符时的情况。这个时候输出应该是什么呢。当然是输入本身。但是,不要忘了输出应该是数组形式,所以接下来的样子:

function permutate(str) {
    var result = [];

    if(str.length > 1) {
    } else if (str.length == 1) {
        return [str];
    }

    return result;
}

中间用了else if 而没有用else的原因是不清楚到最后是否要处理空字符串的情况,所以先留着个else。逻辑上应该位于第一个if里的return语句,放到了最后,比较清晰。

接着进行第二步,假设我们已经知道了n-1的输出,要由这个输出得出n的输出。在这个问题里,n-1的输入,对应着长度比当前输入的字符串少1的输入字符串。也就是说,如果我已经知道了“abc”的全排列输出的集合,现在再给你一个“d”,要怎样得出新的全排列呢?

很简单,只要对于集合中每一个元素,把d插入到任意相邻字母之间(或者头部和尾部),就可以得到一个新的排列。例如对于元素“acb”,插入到第一个位置,即可得到“dacb”,插入其余位置,可得到“adcb”,“acdb”,“acbd”。容易证明这样形成的新元素不会有重复。

在这里,对于每一个输入的str,我们把它分为两部分,第一部分为字符串的第一个字母,定义为left,第二部分为剩余的字符串,定义为rest,根据以上的假设,现在可以把 permutate(rest) 作为一个已知量看待。

function permutate(str) {
    var result = [];

    if(str.length > 1) {
        var left = str[0];
        var rest = str.slice(1, str.length);
        var preResult = permutate(rest);
        /*
          Do some operation
        */
    } else if (str.length == 1) {
        return [str];
    }

    return result;
}

接着对permutate(rest)里的每一个排列进行处理,将left插入到每一个位置中,每得到一个排列,便将它push到result里面去。

......
    for(var i=0; i<preResult.length; i++) {
        for(var j=0; j<preResult[i].length; j++) {
            var tmp = preResult[i],slice(0, j) + left + preResult[i].slice(j, preResult[i].length);
            result.push(tmp);
        }
    }
......

有了字符串自带的slice方法省了不少事。一开始想到插入字符串想到的是splice方法,然而这个方法会对原始字符串进行修改,要是用它的话会出很无奈的bug……

到这里就告一段落了,把上面的片段插入到前面的注释的位置就是完整代码了。

然后这个函数对于空字符串的输入会输出空字符串,所以前面else if的if也可以去掉。

时间: 2024-10-29 00:40:51

全排列算法的JS实现的相关文章

不会全排列算法(Javascript实现),我教你呀!

今天我很郁闷,在实验室凑合睡了一晚,准备白天大干一场,结果一整天就只做出了一道算法题.看来还是经验不足呀,同志仍需努力呀. 算法题目要求是这样的: Return the number of total permutations of the provided string that don't have repeated consecutive letters. Assume that all characters in the provided string are each unique.F

全排列算法 --javascript 实现

(function(){ var ret = new Array(); var A = function a(str){ if(str == undefined || str == null){return new Array();} if(str.length < 2) {return new Array(str);} if(str.length == 2) {return new Array(str[0]+str[1],str[1]+str[0]);} for(var k = 0;k <

全排列算法(转)

列出全排列的初始思想: 解决一个算法问题,我比较习惯于从基本的想法做起,我们先回顾一下我们自己是如何写一组数的全排列的:1,3,5,9(为了方便,下面我都用数进行全排列而不是字符). 1,3,5,9.(第一个) 首先保持第一个不变,对3,5,9进行全排列. 同样地,我们先保持3不变,对5,9进行全排列. 保持5不变,对9对进行全排列,由于9只有一个,它的排列只有一种:9.接下来5不能以5打头了,5,9相互交换,得到 1,3,9,5. 此时5,9的情况都写完了,不能以3打头了,得到 1,5,3,9

两种常用的全排列算法(java)

问题:给出一个字符串,输出所有可能的排列. 全排列有多种算法,此处仅介绍常用的两种:字典序法和递归法. 1.字典序法: 如何计算字符串的下一个排列了?来考虑"926520"这个字符串,我们从后向前找第一双相邻的递增数字,"20"."52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后面找一个比替换数大的最小数(这个数必然存在),0.2都不行,5可以,将5和2交换得到"956

字符串非重复全排列算法

[题目描述] 输入一个字符串,打印出该字符串中字符的所有排列. 例如输入字符串abc,则输出由字符a.b.c 所能排列出来的所有字符串 abc.acb.bac.bca.cab 和 cba. [分析] 从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如此递归处理,从而得到所有元素的全排列.以对字符串abc进行全排列为例,我们可以这么做:以abc为例 固定a,求后面bc的排列:abc,acb,求好后,a和b交换,得到bac 固定b,求后面ac的排列:bac,bca,求好

全排列算法的递归与非递归实现

全排列算法的递归与非递归实现 全排列算法是常见的算法,用于求一个序列的全排列,本文使用C语言分别用递归与非递归两种方法实现,可以接受元素各不相同的输入序列. 题目来自leetcode: Given a collection of numbers, return all possible permutations. For example, [1,2,3] have the following permutations: [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3

java全排列算法实现 --- 小例子实现

Question:猜算式 看下面的算式: □□ x □□ = □□ x □□□ 它表示:两个两位数相乘等于一个两位数乘以一个三位数. 如果没有限定条件,这样的例子很多. 但目前的限定是:这9个方块,表示1~9的9个数字,不包含0. 该算式中1至9的每个数字出现且只出现一次! 比如: 46 x 79 = 23 x 158 54 x 69 = 27 x 138 54 x 93 = 27 x 186 ..... 请编程,输出所有可能的情况! 注意: 左边的两个乘数交换算同一方案,不要重复输出! 不同方

算法(全排列算法封装)

本算法是教材中的全排列方法之一,本人仅做封装,在此感谢发现算法和传播算法的大牛们. /// <summary> /// 全排列算法,算法原理:Perm(n)=[n]*Pern(n-1).N的全排列等于将N个数取一个放在第N个位置后,剩下的N-1个数做全排列. /// 这个算法的一个用途是进行行列式的展开和计算,这也是这次封装这个算法的目的. /// </summary> public class Permulation { /// <summary> /// 排列结果

常见算法是js实现汇总(转载)

常见算法是js实现汇总 /*去重*/ <script> function delRepeat(arr){ var newArray=new Array(); var len=arr.length; for(var i=0;i<len;i++){ for(var j=i+1;j<len;j++) { if(arr[i]==arr[j]) { ++i; } } newArray.push(arr[i]); } return newArray; } var arr=new Array(&