递归回溯
递归与回溯
方法自己调用自己
1)执行方法时创建新栈空间
2)方法的局部变量独立
3)方法使用引用类型变量时,共享此数据
4)递归边界
5)方法全部执行完返回
1.n皇后问题
/**
* 8皇后问题
*/
public class Queens {
int max = 8;
int sum = 0;
//保存第 i 个皇后的列号
int[] array = new int[max];
public static void main(String[] args) {
Queens queens = new Queens();
queens.check(0);
queens.print();
}
//放置皇后
private void check(int n) {
if (n == max) {
sum++;
return;
}
//依次放置
for (int i = 0; i < max; i++) {
array[n] = i;
if (judge(n)) {
check(n + 1);
}
}
}
//检测是否冲突
private boolean judge(int n) {
for (int i = 0; i < n; i++) {
//位于同一列/同斜线
if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
return false;
}
}
return true;
}
//输出
private void print() {
// for (int i = 0; i < array.length; i++) {
// System.out.println(array[i] + " ");
// }
System.out.println(sum);
}
}
2.回溯
2.1 生成括号
/**
* 给出n对括号,请编写一个函数来生成所有的由n对括号组成的合法组合
*/
public class Solution {
/**
*
* @param n int整型
* @return string字符串ArrayList
*/
ArrayList<String> ans = new ArrayList<String>();
public ArrayList<String> generateParenthesis (int n) {
gen("",0,0,n);
return ans;
}
//确定分支和边界条件
private void gen(String s,int i,int j,int n){
if(j == n){
ans.add(s);
}
if(i < n){
gen(s+"(",i+1,j,n);
}
if(j < i){
gen(s+")",i,j+1,n);
}
}
}
2.2 字符串转化成IP地址
/**
* 现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
*/
public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
ArrayList<String> ans = new ArrayList<String>();
public ArrayList<String> restoreIpAddresses (String s) {
gen("",0,0,0,s);
return ans;
}
private void gen(String ip,int left,int right,int n,String s){
//分析边界条件
if(n > 4) return;
String t = "";
if(n > 0){
t = s.substring(left,right);
int num = Integer.parseInt(t);
if(num < 0 || num > 255 || t.length() > Integer.toString(num).length()) return;
ip = ip+"."+t;
}
//成功返回
if(n == 4 && right == s.length()){
ans.add(ip.substring(1));
return;
}
//分支递归
if(right+1 <= s.length()) gen(ip,right,right+1,n+1,s);
if(right+2 <= s.length()) gen(ip,right,right+2,n+1,s);
if(right+3 <= s.length()) gen(ip,right,right+3,n+1,s);
}
}
2.3 n中取k个组合(剪枝优化)
/**
* 给出两个整数n和k,返回从1到n中取k个数字的所有可能的组合
*/
public class Solution {
ArrayList<ArrayList<Integer>> ans;
public void check(int n,int k,int start,ArrayList<Integer> com){
//返回
if(k == com.size()){
ans.add(new ArrayList<Integer>(com));
return;
}
//减少不符合的情况
if(start > n) return;
//com当中最终应该有k个元素,当前元素为com.size() + 1,那么我们要为下次回溯留下足够多的数
int len = k - 1 - com.size();
for(int i = start;i <= n - len;i++){
com.add(i);
check(n,k,i+1,com);
com.remove(com.size()-1);
}
}
public ArrayList<ArrayList<Integer>> combine (int n, int k) {
//基本构造如套路
ans = new ArrayList<ArrayList<Integer>>();
if( n <= 0 || k <= 0 || n < k) return ans;
check(n,k,1,new ArrayList<Integer>());
return ans;
}
}
如果自己都不相信自己了,那该如何呢?

浙公网安备 33010602011771号