回溯问题,就是决策树的遍历过程,回溯问题须要有下面几个问题考虑框架
路径:已经作出的选择,即从根节点到当前节点的路径大数据
选择列表:当前状况下还能够作哪些选择,即继续往下遍历节点,能够走哪些路优化
结束条件:到达决策树的叶子节点,或者不知足条件中止人工智能
明白回溯问题的几个问题后,咱们来看,回溯的基本框架rest
List<String> result = new ArrayList<String>(); public void backtrack(已经选择的路径,能够作选择的列表) { if (知足结束条件) result.add(已经选择的路径); return; for 选择 in 能够作选择的列表 { 选择列表.remove(选择); 已经选择的路径.add(选择); backtrack(已经选择路径,能够作选择的路径); //撤销 已经选择的路径.remove(选择); 能够作选择的列表.add(选择); } }
光学不练假把式,在看到思路前,先本身写一遍实现,再看有没有能够优化的地方.code
给定一个 没有重复 数字的序列,返回其全部可能的全排列。来源:https://leetcode-cn.com/problems/permutations/ip
示例:leetcode
//输入: [1,2,3] //输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
class Solution { public List<List<Integer>> permute(int[] nums) { List<List<Integer>> res = new ArrayList<>(); int[] visited = new int[nums.length]; backtrack(res, nums, new ArrayList<Integer>(), visited); return res; } private void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) { if (tmp.size() == nums.length) { res.add(new ArrayList<>(tmp)); return; } for (int i = 0; i < nums.length; i++) { if (visited[i] == 1) continue; visited[i] = 1; tmp.add(nums[i]); backtrack(res, nums, tmp, visited); visited[i] = 0; tmp.remove(tmp.size() - 1); } } }
注: 其中res
是全局返回,tmp是当前路径上的节点,visited
和 nums
来标识当前还有哪些节点能够访问rem
给定一个只包含数字的字符串,复原它并返回全部可能的 IP 地址格式。来源:https://leetcode-cn.com/problems/restore-ip-addresses/字符串
有效的 IP 地址 正好由四个整数(每一个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
例如:"0.1.2.201" 和 "192.168.1.1" 是 有效的 IP 地址,可是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效的 IP 地址。
示例 1:
输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
示例 2:
输入:s = "0000"
输出:["0.0.0.0"]
示例 3:
输入:s = "1111"
输出:["1.1.1.1"]
示例 4:
输入:s = "010010"
输出:["0.10.0.10","0.100.1.0"]
示例 5:
输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
解决代码
class Solution { public List<String> restoreIpAddresses(String s) { List<String> res = new ArrayList(); List<String> temp = new ArrayList(); helper(res,temp,s); return res; } void helper(List<String> res,List<String> temp,String next) { if(temp.size() > 4) { return; } if(temp.size() == 4 && next.length() == 0) { String ip = temp.get(0) + "." + temp.get(1) + "." + temp.get(2) + "." + temp.get(3); res.add(ip); return; } for(int i = 0; i < next.length(); i++) { String s = next.substring(0,i+1); if(s.length() > 1 && s.charAt(0) == '0') { continue; } if(s.length() > 3) { continue; } if(s.length() == 3 && "255".compareTo(s) < 0) { continue; } temp.add(s); helper(res,temp,next.substring(i+1)); temp.remove(temp.size() - 1); } } }
注: 总体框架仍是采用上面的结构,不过在判断当前节点是否应该加入temp时候,要作一点稍微复杂的判断
吴邪,小三爷,混迹于后台,大数据,人工智能领域的小菜鸟。
更多请关注