[LeetCode] 劍指 Offer 38. 字串的排列
阿新 • • 發佈:2021-06-23
回溯DFS
但是該遞迴函式並沒有滿足「全排列不重複」的要求,在重複的字元較多的情況下,該遞迴函式會生成大量重複的排列。對於任意一個空位,如果存在重複的字元,該遞迴函式會將它們重複填上去並繼續嘗試導致最後答案的重複。
解決該問題的一種較為直觀的思路是,我們首先生成所有的排列,然後進行去重。而另一種思路是我們通過修改遞迴函式,使得該遞迴函式只會生成不重複的序列。
具體地,我們只要在遞迴函式中設定一個規則,保證在填每一個空位的時候重複字元只會被填入一次。具體地,我們首先對原字串排序,保證相同的字元都相鄰,在遞迴函式中,我們限制每次填入的字元一定是這個字元所在重複字元集合中「從左往右第一個未被填入的字元」,即如下的判斷條件:
if (vis[j] || (j > 0 && !vis[j - 1] && s[j - 1] == s[j])) {
continue;
}
這個限制條件保證了對於重複的字元,我們一定是從左往右依次填入的空位中的。
class Solution { public String[] permutation(String s) { List<Character> notUsed = new ArrayList<>(); for (int i=0;i<s.length();i++) { notUsed.add(s.charAt(i)); } Set<String> ans = new HashSet<>(); dfs(ans, notUsed, ""); String[] arr = new String[ans.size()]; return ans.toArray(arr); } public void dfs(Set<String> ans, List<Character> notUsed, String cur) { if (notUsed.size() == 0) { ans.add(cur); return; } for (int i=0;i<notUsed.size();i++) { List<Character> newList = new ArrayList<>(notUsed); newList.remove(i); dfs(ans, newList, cur + notUsed.get(i)); } } }