1

几个数组元素的排列组合问题。比如['A','B'],['C','D','E'],['F','G'],其排列组合的结果是['A','C','F'],['A','C','G'],['A','D','F'],......,['B','E','F'],['B','E','G'],共有2x3x2=12种结果,那么,如何用程序实现。

简单的思路就是先把前面两个数组的元素做排列组合,产生的新数组再和后面的数组做排列组合,始终是在做两个数组的排列组合操作。

function sku(arr){
    if(arr.length<1) return null;
    if(arr.length<2) return arr[0];
    var result=[];
    var firstArr=arr[0];
    for(var i = 0 ; i < firstArr.length ; i ++){ //这里是将第一个数组里面的元素变成数组,方便后续进行concat操作。
        result.push([firstArr[i]]);
    }
    arr.splice(0,1,result);
    while(arr.length>1){
        var targetArr=arr[0];   
        var nextArr=arr[1];
        var result=[];
        for(var i = 0 ; i < targetArr.length; i ++){//进行排列组合
            for(var j = 0 ; j < nextArr.length; j ++){
               var tmp=([].concat(targetArr[i]));  //将数据复制到新的数组里面,因为后续targetArr[i]还会被用到。不能直接更改targetArr[i]这个数组。
               tmp.push(nextArr[j]);//
               result.push(tmp);
            }
        }
        arr.splice(0,2,result);//前面两个数组已经完成了排列组合,结果在result中,所以替换掉。
    }
 }

以arr=[['A','B'],['C','D','E'],['F','G']]作为输入。

 for(var i = 0 ; i < firstArr.length ; i ++){ //这里是将第一个数组里面的元素变成数组,方便后续进行concat操作。
        result.push([firstArr[i]]);
    }

arr的结果就变成了[[['A'],['B']],['C','D','E'],['F','G']].
然后经过第一次循环,将[['A'],['B']],['C','D','E']两个数组合并,
变成了result这个数组的内容是[['A','C'],['A','D'],['A','E'],['B','C'],['B','D'],['B','E']].

arr.splice(0,2,result);

将合并后的数组去除,然后将合并的结果放到原数组列表里面,数组长度-1,当原数组只有一个元素时,就是最终结果。


偶然看到一个求字符串内字符全排列的算法

比如给定一个字符串"abc",得出的结果是abc,acb,bac,bca,cab,cba.
该方法是通过递归完成的。

var result = [];
function permutations(str){
    var arr= str.split('');
    helper(arr,0,[]);
    return result;
}
function helper(arr,index,list){
    if(index === arr.length){
        result.push(list.join(''));
        return;
    }
    for(var i = 0;i<arr.length;i++){
        if(list.indexOf(arr[i]) != -1){//这一步是为了避免重复字符
            continue;
        }
        list.push(arr[i]);
        helper(arr,index+1,list)
        list.pop();//这一步是为了求得所有的结果。
    }
}

大意是指每次从原数组里面选择一个目标数组里面没有的字符串,直到目标数组长度和原数组一样,然后做一个join就得出了结果。

然后我发现我上面的方法也能达成这个目的,只不过要构建字符串长度这么多的数组。
每个数组的内容都一样,就是字符串split("")以后的结果。
然后为了保证不重复,可以把for循环中加一句。

     for(var i = 0 ; i < targetArr.length; i ++){
            for(var j = 0 ; j < nextArr.length; j ++){
               var tmp=([].concat(targetArr[i]));  
               if(tmp.indexOf(nextArr[j])!=-1) continue;  //加上这一行,起到无重复字母的效果
               tmp.push(nextArr[j]);
               result.push(tmp);
            }
        }

在网上看了很多算法,学习了很多。有对的,也有错的;有的简单有效,有的疯狂绕圈。有时候觉得高深莫测,看懂了以后发现完全没必要。还是自己试试。


好多知识不知道
21 声望0 粉丝

想法,每个人都有,每时每刻。想法并不会一直留在脑中,时间会遗忘一切,有必要整理一些东西,记住那时的你。思维是最美的东西,让不同时间的你,用思维对话。(起高了)