[動的計画法、再帰的バックトラッキング]文字列の配置

タイトル説明

文字列を入力し、文字列内のすべての文字を辞書式順序で出力します。たとえば、文字列abcを入力し、文字a、b、cで辞書式順序に並べることができるすべての文字列abc、acb、bac、bca、cab、およびcbaを出力します。

文字列を入力します。長さは9を超えません(文字が繰り返される場合があります)。文字には大文字と小文字のみが含まれます。

入力
"ab"と
戻り値
["ab"、 "ba"]


動的計画法

動的計画法のアイデアは、問題をサブ問題に分解し、最小のサブ問題から始めて、サブ問題を拡張し続け、サブ問題の解決策を使用して、元の問題まで大きな問題を解決することです問題は解決されました。

文字列配置の場合、最小のサブ問題は単一の文字であり、その配置はそれ自体であり、最後に文字を追加し続けます。たとえば、現在の問題を想定して、文字を追加するときに前のサブ問題の配置結果を使用します。あるabcそのサブ問題がされていることabと仮定すると、abソリューションは、我々はすでに知っているされて{ab, ba}、このソリューションに基づいて新しい文字の挿入c。例えばab、それを得ることができる{cab, acb, abc}baの根拠ソリューション、そして同じことが得られるの基礎同じ。解決策{cba, bca, cab}問題がabcされて最終的に得られる{cab, acb, abc, cba, bca, cab}。アイデアは非常に直感的です。

実装の過程で、繰り返されるソリューションの存在を回避するために、1つHashMap使用して結果を保存し、重複を自動的に削除して、最後にそれらをソートします。

public ArrayList<String> Permutation(String str) {
    
    
   HashMap<String, Integer> hashMap = new HashMap<>();
    int len = str.length(); // 获取字符串长度
    hashMap.put(str.substring(0, 1), 1);
    for (int i = 1; i < len; i++) {
    
    
        HashMap<String, Integer> tmp = new HashMap<>();
        String insert = str.substring(i, i + 1);
        for (String s : hashMap.keySet()) {
    
    
            // 在每个字符串中从前到尾插入当前字符
            for (int j = 0; j < s.length() - 1; j++) {
    
    
                String front = s.substring(0, j + 1), behind = s.substring(j + 1);
                tmp.put(front + insert + behind, 1);
            }
            // 头和尾
            tmp.put(insert + s, 1);
            tmp.put(s + insert, 1);
        }
        hashMap = tmp;
    }
    ArrayList<String> res = new ArrayList<>();
    for (String s : hashMap.keySet())
        res.add(s);
    // 排序
    Collections.sort(res);
    return res;
}

再帰的なバックトラック

再帰的メソッドのアイデアは、次の図(画像参照)に示すように、最初の文字を次の文字と交換します。各文字が先頭にあるすべての状況を取得し、最初の文字を修正して
、部分文字列を再帰的に修正する部分文字列の解決策は、前部を修正することでもあります。この場合、2番目の文字と後続のすべての文字が交換され、最初の2文字が修正され、部分文字列の解決策が検索されます。

再帰的終了とは、文字列が1文字しかない場合で、この時点で配置された結果を保存できます。

ここに画像の説明を挿入します

実装では、文字列内の2つの位置の値が頻繁に交換Stringされるためchar最初に配列に変換されます。これは、交換中により効率的です。

public ArrayList<String> Permutation(String str) {
    
    
	ArrayList<String> res = new ArrayList<>();
	PermutationHelper(str.toCharArray(), 0, res);
	// 排序
	Collections.sort(res);
	for (String s : res)
		System.out.print(s + " ");
	return res;
}

public static void PermutationHelper(char[] str, int index, ArrayList<String> res) {
    
    
	if (index == str.length - 1) {
    
    
		// 若不重复则添加到结果中
		if (!res.contains(String.valueOf(str))) res.add(String.valueOf(str)); 
		return;
	}
	for (int i = index; i < str.length; i++) {
    
    
		// swap index and i
		swap(str, index, i);
		PermutationHelper(str, index + 1, res);
		swap(str, i, index); // 需要交换回来,不改变str的值
	}
}

public static void swap(char[] str, int i, int j) {
    
    
	char temp = str[i];
	str[i] = str[j];
	str[j] = temp;
}

おすすめ

転載: blog.csdn.net/weixin_43486780/article/details/113759589