简介
回溯法(Backtracking)使用递归,依次枚举 各个阶段的可能值,形成所有可能的多阶段决策,并且(剪枝)在递归过程中避免枚举不正确的可能。
最经典的题目是 全排列、8皇后、所有子集、所有组合、0/1背包等等
回溯模式
void backtrack ( int i )
{
/* prune:剪枝 */
if ( solution [] will not be an answer ) return ;
/* 有了一组多阶段决策,并检验正不正确 */
if ( dimension == MAX_DIMENSION )
{
check and record solution [];
return ;
}
/* 穷举这个阶段的所有可能,并递归到下一个阶段 */
for ( x = possible value of current i )
{
solution [i] = x ;
backtrack ( i + 1 );
}
}
例题
leetCode 1239. 串联字符串的最大长度
给定一个字符串数组 arr,字符串 s 是将 arr 某一子序列字符串连接所得的字符串,如果 s 中的每一个字符都只出现过一次,那么它就是一个可行解。
请返回所有可行解 s 中最长长度。
public int maxLength(List<String> arr) {
int[] cnt = new int[26];
int res = backTrack(0, cnt, "", arr);
return res;
}
int backTrack(int i,int[] cnt, String str, List<String> arr) {
if (i == arr.size()) {
return str.length();
}
int res = backTrack(i+1,cnt, str, arr); // 0 不取当前串
String cur = arr.get(i);
int[] curcnt = new int[26];
if (uniqChar(cur, curcnt) && !conflict(cnt, curcnt)) { //1 该单词无重复字符 且与当前解不冲突
int temp = backTrack(i+1, curcnt, str+arr.get(i), arr);
if (temp > res) {
res = temp;
}
}
return res;
}
boolean uniqChar(String str, int[] cnt) {
for (char c: str.toCharArray()) {
cnt[c-'a'] ++;
if (cnt[c-'a']>1) return false;
}
return true;
}
boolean conflict(int[] cnt, int[] curcnt) {
for (int i=0;i<cnt.length;i++) {
curcnt[i] += cnt[i];
if (curcnt[i] > 1) return true;
}
return false;
}
public static void main(String[] args) {
String[] arr = {"un","iq","ue"};
System.out.println(new MaximumLengthOfAConcatenatedStringWithUniqueCharacters_1239().maxLength(Arrays.asList("abcdefghijklmnowpqrstuvwxyz")));
}