回溯是 DFS 的一种,它不是用在遍历图的节点上,而是用于求解 排列组合 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串。
在程序实现时,回溯需要注意对元素进行标记的问题。使用递归实现的回溯,在访问一个新元素进入新的递归调用,此时需要将新元素标记为已经访问,这样才能在继续
递归调用时不用重复访问该元素;但是在递归返回时,需要将该元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,而在不同的递归链是可以访问
已经访问过但是不在当前递归链中的元素。
回溯算法的标准格式:
回溯法伪代码 back(c,digits,offset,res){ if(offset==length){ res.add(); return; } for(char c:String.toCharArray()){ back(c,digits,offset+1,res); } }
leetcode 17
最终代码
class Solution { public static final String[] key={"","","abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; // 回溯法伪代码 // back(c,digits,offset,res){ // if(offset==length){ // res.add(); // return; // } // for(char c:String.toCharArray()){ // back(c,digits,offset+1,res); // } // } public List<String> letterCombinations(String digits) { List<String> res=new ArrayList<>(); if(digits!=null&&digits.length()!=0){ back("",digits,0,res); } return res;//如果最终结果不对,可以直接诊断return附近哪里逻辑写错了 } public void back(String pre,String digits,int offset,List<String> res){ if(offset==digits.length()){ res.add(pre); return; } String letters=key[digits.charAt(offset)-'0']; for(char ch:letters.toCharArray()){ back(pre+ch,digits,offset+1,res); } } }
leetcode 79