1. 程式人生 > 其它 >每日演算法之字串的排列

每日演算法之字串的排列

JZ38 字串的排列

描述

輸入一個長度為 n 字串,打印出該字串中字元的所有排列,你可以以任意順序返回這個字串陣列。
例如輸入字串ABC,則輸出由字元A,B,C所能排列出來的所有字串ABC,ACB,BAC,BCA,CBA和CAB。

題目主要資訊
給定一個長度為n的字串,求其中所有字元的全排列
字串中可能有重複字元,列印順序任意
字串中只包含大小寫字母

思路

都是求元素的全排列,字串與陣列沒有區別,一個是數字全排列,一個是字元全排列。為了便於去掉重複情況,還是參照陣列全排列,優先考慮字典序排序,因為排序後重復的字元就會相鄰,後序遞迴找起來也很方便
使用臨時變數去組裝一個全排列情況:每當我們選取一個字元以後,就確定了其位置,相當於對字串中剩下的元素進行全排列新增在該元素的後面,給剩餘部分進行全排列就是一個子問題,因此可以使用遞迴。

終止條件:臨時字串中選取了n個元素,已經形成了一種排列情況,可以將其加入輸出陣列中。
返回值:每一層給上一層返回的就是本層級在臨時字串中新增的元素,遞迴到末尾的時候,就能新增全部元素

具體做法

先對字串按照字典序排序,獲得第一個排列情況

準備一個空串,暫存遞迴過程中組裝的排列情況。使用額外的vis陣列用於記錄哪些位置的字元被加入了

每次遞迴從頭遍歷字串,獲取字元加入:首先根據vis陣列,已經加入的元素不能再加入了;同時,如果當前的元素str[i]與同一層的前一個元素str[i-1]相同,且str[i-1]已經用,也不需要將其加入

進入下一等遞迴前將vis陣列當前位置標記為使用過

回溯時,需要修改vis陣列當前位置標記,同時去掉剛剛加入的字串元素

臨時字串長度達到原串長度就是一種排列情況

程式碼

package mid.JZ38字串的排列;

import java.util.ArrayList;
import java.util.Arrays;

public class Solution {

    private StringBuilder builder = new StringBuilder();

    private ArrayList<String> res = new ArrayList<>();

    public ArrayList<String> Permutation(String str) {

        if (str == null || str.length() == 0) {
            return res;
        }

        char[] chars = str.toCharArray();
        Arrays.sort(chars);
        String sortedStr = new String(chars);

        //當vis[i]=0,表示index為0的字元沒有被使用
        //當vis[i]=1,表示index為1的字元被使用了
        int[] vis = new int[chars.length];

        dfs(sortedStr, vis, 0);

        return res;
    }

    private void dfs(String str, int[] vis, int depth) {

        if (builder.length() == str.length()) {
            res.add(builder.toString());
            return;
        }

        for (int i = 0; i < str.length(); i++) {
            if (vis[i] == 1) {
                continue;
            }
            //當前的元素str[i]與同一層的前一個元素str[i-1]相同且str[i-1]已經用過了
            if (i != 0 && str.charAt(i) == str.charAt(i - 1) && vis[i - 1] == 1) {
                continue;
            }
            builder.append(str.charAt(i));
            vis[i] = 1;
            dfs(str, vis, depth + 1);
            builder.deleteCharAt(builder.length() - 1);
            vis[i] = 0;
        }
    }

    public static void main(String[] args) {
        System.out.println(new Solution().Permutation("ab"));
    }
}