回溯算法:
从一条路往前走,能进则进,不能进则退回来,换一条路再试。(以深度优先方式搜索)
回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择。
使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束
用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。
回溯法的实现方法有两种:递归和递推(也称迭代)。一般来说,一个问题两种方法都可以实现,只是在算法效率和设计复杂度上有区别。
递归思路简单,设计容易,但效率低。递推算法设计相对复杂,但效率高。
集合求幂集函数:
public class Test{
public static void main(String []args){
List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
List<String> li = new ArrayList<String>();
print(0,list,li);
}
public static void print(int i, List<String> list, List<String> li){
if(i > list.size()-1){
System.out.println(li);
}else{
li.add(list.get(i)); //左子树的处理
print(i+1,list,li); //递归遍历
li.remove(list.get(i)); //右子树的处理
print(i+1,list,li); //递归遍历
}
}
}
皇后问题:
public class Test{
static int max = 8; //放置几个皇后
static int num = 0; //总共有几种存放方式
static int[] array = new int[max]; //用数组存放皇后的摆放位置 用来判断是否摆放正确
public static void main(String[] args){
check(0); //先放第一个皇后
System.out.println(num);
}
public static void check(int n){
if(n == max){ //如果皇后全部摆放完成 ,总数+1 并跳出该方法
num++;
return;
}
for (int i = 0; i < max; i++) { //从第一列开始放,到第max列为止
array[n] = i; //默认该皇后都是从该行的第一列开始摆放
if (ok(n)) { //判断该皇后的摆放位置是否正确
check(n + 1); //如果正确,则递归下一个皇后的摆放
}
}
}
private boolean ok(int n) {
for (int i = 0; i < n; i++) { //从第一列开始放值,然后判断是否和本行本列本斜线有冲突,如果OK,就进入下一行的逻辑
//array[i] == array[n] 判断是否在同一斜线上
//Math.abs(n - i) == Math.abs(array[n] - array[i]) 判断是否在同一行或列
if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
return false;
}
}
return true;
}
}