回溯法

回溯法是暴力法的升级版本,问题的解决是一步一步向下进行的,而每一步又会有有限个选项步,则可以构建一棵多叉树,每个根节点如果匹配则进入该节点的子节点,继续向下匹配,匹配失败则回到父节点的其他子节点向下匹配,如果父节点的所有节点都无法向下匹配成功,则回溯到父节点的父节点,访问爷爷节点的其他字节点,这个过程可以由递归来实现,也就可以用栈来实现和理解。我们便利所有的元素,让其成为入口,也就是根节点,这个时候根节点的方法入栈,如果根节点匹配了,继续向根节点的子节点访问,根节点的子节点的方法入栈,如果该根节的子节点都无法匹配,则该子节点出栈,回溯根节点的其他子节点,继续。如果完全匹配,则返回成功。如果完全便利,都没能匹配,则返回失败。

package jzof_ex;
import java.util.*;
public class Jzof_12 {

    class node{
        public int x;
        public int y;
        node(int x,int y){
            this.x=x;
            this.y=y;
        }
    }

    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        if (matrix == null || rows < 0 || cols < 0 || str == null)
            return false;

        boolean[][] visit = new boolean[rows][cols];
        //Stack tmp = new Stack();
        int index = 0;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (match(matrix, rows, cols, str, i, j, index, visit)) {
                    // match()
                    return true;
                }
            }
        }
        return false;
    }
    
    public boolean match(char[] matrix, int rows, int cols, char[] str, int i, int j,int index,boolean[][] visit) {

        if(index>=str.length) {//如果比较的是index>str.length-1,则当访问到index-2的时候,匹配,index++,则index=str.length-1
                               //在index=length-1,就返回存在的问题是,字符串的最后一个字符没有匹配
            return true;
        }
        boolean hasmatch=false;
        //tmp.push(new node(i,j));
        if (i>=0&&i=0&&j
注意

从上面的代码也可以看出来,回溯的实现体现在当前节点的所有子节点都无法匹配的时候,会弹出当前节点。

public class Solution {
    public int movingCount(int threshold, int rows, int cols)
    {
        boolean[][] visit=new boolean[rows][cols];
        int num=0;
        match(threshold,rows,cols,0,0,visit);
        for(int i=0;i0) {
            sum=sum+a%10;
            a=a/10;                
        }
        return sum;
    }
    public boolean match(int threshold,int rows,int cols,int i,int j,boolean[][] visit) {
        int a = sumEachSite(i) + sumEachSite(j);
        boolean hasmatch = false;
        if (a <= threshold && i < rows && i >= 0 && j < cols && j >= 0&&visit[i][j] != true) {
            visit[i][j] = true;
            hasmatch = match(threshold, rows, cols, i, j - 1, visit) || match(threshold, rows, cols, i, j + 1, visit)
                    || match(threshold, rows, cols, i - 1, j, visit) || match(threshold, rows, cols, i + 1, j, visit);
        }
        return hasmatch;
    }
}

递归实现计数求和的版本

package jzof_ex;

public class Jzof_13 {

    public int movingCount(int threshold, int rows, int cols)
    {
        boolean[][] visit=new boolean[rows][cols];
        int num=Count(threshold,rows,cols,0,0,visit);
        return num;
    }
    
    public int sumEachSite(int i) {
        int a=i;
        int sum=0;
        while(a>0) {
            sum=sum+a%10;
            a=a/10;                 
        }
        return sum;
    }
    
    public int Count(int threshold,int rows,int cols,int i,int j,boolean[][] visit) {
        int count=0;
        if (match(threshold,rows,cols,i,j,visit)) {
            visit[i][j] = true;
            count=1+Count(threshold, rows, cols, i, j - 1, visit)+Count(threshold, rows, cols, i, j + 1, visit)
                   +Count(threshold, rows, cols, i - 1, j, visit)+Count(threshold, rows, cols, i + 1, j, visit);
        }
        return count;
    }
    public boolean match(int threshold,int rows,int cols,int i,int j,boolean[][] visit) {
        if (sumEachSite(i) + sumEachSite(j)<= threshold && i < rows && i >= 0 && j < cols && j >= 0&&visit[i][j]!=true) {
            return true;
        }
        return false;
        
    }
}

对于递归的理解和回溯法的理解,其实都是对于栈的理解和分治法的理解,当然对于回溯法不能完全说是分治,有点像forkjoinpool的感觉,因为约束条件的不同,使得具体操作会不一样,但是思想都是一样的,我们每一步知道有多少条路,每条路都向下走到黑,成功返回true,失败返回false,同时回溯,把所有的路径遍历一遍即可得到问题的解。当然在就行匹配的时候,或者说约束条件匹配的时候,我们的返回值或者说进行的操作不是固定死的,就比如下面的例子,在匹配成功的时候,我们还进行了计数,所以要理解的更深入些,这是一种解决问题的思想,具体的操作都可以。

你可能感兴趣的:(回溯法)