LeetCode-131。分割回文文字列-バックトラッキング+剪定

131.分割回文

タイトル説明

文字列sを指定します。各部分文字列が回文文字列になるように、sをいくつかの部分文字列に分割してください。の可能なすべての分割スキームを返します。

回文は、前方と後方の両方で読み取られる文字列です。

例1:

入力:s = "aab"
出力:[["a"、 "a"、 "b"]、["aa"、 "b"]]
例2:

入力:s = "a"
出力:[["a"]]

問題解決のアイデア

ここに画像の説明を挿入

  1. 各ノードはスキャンされていない残りの文字列を表し、生成されるブランチは残りの文字列のプレフィックスをインターセプトすることです。

  2. プレフィックス文字列を生成するときは、プレフィックス文字列が回文であるかどうかを確認します。

  • プレフィックス文字列が回文の場合、ブランチとノードを生成できます。
  • プレフィックス文字列が回文でない場合、ブランチとノードは生成されません。このステップは剪定操作です。
  1. リーフノードが空の文字列の場合の決済この時点で、ルートノードからリーフノードへのパスが結果セットの結果になります。深さ優先走査を使用して、考えられるすべての結果を記録します。

  2. パス変数パスを使用して検索し、1つのパスをグローバルに使用します(決済中にコピーが生成されることに注意してください)。したがって、再帰実行メソッドが終了した後、バックトラックする必要があります。つまり、再帰の前に追加された要素を削除します。

  3. パス操作はリストの最後にのみあるため、適切なデータ構造はスタックです。

class Solution_131 {
    
    
    public List<List<String>> partition(String s) {
    
    
        int len = s.length();
        List<List<String>> res = new ArrayList<>();
        if (len == 0){
    
    
            return res;
        }
        Deque<String> stack = new ArrayDeque<>();
        char[] charArray = s.toCharArray();
        dfs(charArray,0,len,stack,res);
        return res;
    }

    /**
     *
     * @param charArray
     * @param index 起始字符的索引
     * @param len 字符串s的长度,可以设置为全局变量
     * @param path 记录从根节点到叶子节点的路径
     * @param res 记录所有的结果
     */
    private void dfs(char[] charArray, int index, int len, Deque<String> path, List<List<String>> res) {
    
    
        if (index == len){
    
    
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = index; i <len; i++){
    
    
            //因为截取字符串是消耗性能的,采用传子串的方式判断一个子串是否是回文子串
            if (!checkPalindrome(charArray,index,i)){
    
    
                continue;
            }
            path.addLast(new String(charArray,index,i+1-index));
            dfs(charArray,i+1,len,path,res);
            path.removeLast();
        }
    }

    /**
     * 采用动态规划,把回文子串的结果记录在一个表格里
     * @param charArray
     * @param left 子串的左边界,可以取到
     * @param right 子串的右边界,可以取到
     * @return
     */
    private boolean checkPalindrome(char[] charArray, int left, int right) {
    
    
        while (left < right){
    
    
            if (charArray[left] != charArray[right]){
    
    
                return false;
            }
            left++;
            right--;
        }
        return true;
    }


}

おすすめ

転載: blog.csdn.net/qq_35655602/article/details/115057256