【20190405】算法-輸入一個字符串,按字典序打印出該字符串中字符的全部排列

方法一:利用遞歸

利用遞歸求全排列的過程真的很難理解,先把代碼貼上來吧數組

function Permutation(str)
{
    // write code here
    if(!str){
        return str;
    }
    let len=str.length,
        result=[];
    str=str.split('');// 字符串的索引屬性都是隻讀,後面要交換兩個字符的話仍是要先把字符串轉化爲數組
    str.sort();// 直接把字符串按字典序排列了,後面求全排列時也會按照字典序

    Permutate(str,0);
    result=[...new Set(result)];// 這裏是經過Set的特性去重,處理字符串中有重複字符的狀況
    return result.toString();// 最後輸出的仍是字符串

    function Permutate(str,index) {
        if(index===str.length){
            let s='';
            for(let i=0;i<str.length;i++){
                s+=str[i];
            }// 這裏是把數組從新轉回字符串
            result.push(s);
        } else {
            for(let i=index;i<str.length;i++){
                [str[index],str[i]]=[str[i],str[index]];
                Permutate(str,index+1);
            }
        }
    }
}

裏面有幾個坑要注意,一是經過字符串索引是不能修改字符串的,所以仍是要把字符串轉化爲數組;二是注意對重複字符的處理spa

方法二:回溯法

回溯法相對來講更好理解一些,實際上就是對排列結果的每一位遍歷可能的取值。好比首先看第一位,它可能取到字符串裏的每個不重複字符,那麼就遍歷字符串按順序把每一個字符都安到第一位上。若是第一位取到了a,那麼再看第二位,就是從除去a的剩下的字符裏面取。若是字符所有被取完了,那麼將這個排列壓入結果數組裏,而後回溯到上一位。並且這個時候也要回復到上一位的狀態,就是把最後選擇的那個字符從排列裏去掉,從新壓回剩餘字符裏。code

function Permutation2(str){
    // write code here
    if(!str){
        return str;
    }
    let len=str.length,
        result=[],
        s='';
    str=str.split('');
    str.sort();

    Permutate(str);
    result=[...new Set(result)];
    return result.toString();

    function Permutate(str) {
        if(str.length===0){
            result.push(s);
        }else{
            let marked=new Set();
            for (let i=0;i<str.length;i++){
                if (!marked.has([str[i]])){
                    let char=str.splice(i,1);
                    s+=char;
                    Permutate(str);
                    str.splice(i,0,char);//把取的字符從新壓回剩餘字符裏
                    s=s.slice(0,s.length-1);//把取的字符從排列結果裏刪除
                    marked.add(char);//標記該字符已經被取過了
                }
            }
        }
    }
}
相關文章
相關標籤/搜索