leetcode算法题-剑指Offer篇(4)

1、 矩阵中的路径

1.1 题目描述:

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]

但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

1.2 题解

1.2.1 深度优先搜索 DFS

 public boolean exist(char[][] board, String word) {
        char[] words = word.toCharArray();

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (dfs(board, words, i, j, 0)) return true;
            }
        }
        return false;
    }

    /**
     * @param board 矩阵
     * @param word  目标字符串
     * @param i     矩阵行
     * @param j     矩阵列
     * @param k
     * @return
     */
    public boolean dfs(char[][] board, char[] word, int i, int j, int k) {
        if (i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;
        if (k == word.length - 1) return true;
        char temp = board[i][j];
        board[i][j] = '/';//标记已读
        boolean result =  dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || 
                      dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);
        board[i][j] = temp;//将标记取消
        return result;
    }

2、机器人的运动范围

2.1 题目描述:

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
示例 1:
输入:m = 2, n = 3, k = 1
输出:3

2.2 题解

2.2.1 深度优先

 public int movingCount(int m, int n, int k) {
        if (m <= 0 || n <= 0 || k < 0)
            return 0;
        int[] visit = new int[m * n];
        return help(0, 0, k, m, n, visit);

    }
    /**
     * @param row   行
     * @param col   列
     * @param k
     * @param m
     * @param n
     * @param visit 是否已经计算过
     * @return
     */
    public int help(int row, int col, int k, int m, int n, int[] visit) {
        if (row < 0 || col < 0 || row >= m || col >= n || visit[row*n+col] == 1 || sum(row, col) > k)
            return 0;
        visit[row * n + col] = 1;
        return 1 + help(row + 1, col, k, m, n, visit)
                + help(row - 1, col, k, m, n, visit)
                + help(row, col + 1, k, m, n, visit)
                + help(row, col - 1, k, m, n, visit);
    }
    /**
     * 计算和
     * @param m
     * @param n
     * @return
     */
    public int sum(int m, int n) {
        int sum = 0;
        while (m != 0) {
            sum += m % 10;
            m /= 10;
        }
        while (n != 0) {
            sum += n % 10;
            n /= 10;
        }
        return sum;
    }
2.2.2 广度优先
public int movingCount(int m, int n, int k) {
        boolean[] visited = new boolean[m * n];
        int res=0;
        Queue<int[]> queue=new LinkedList<>();
        queue.add(new int[]{0,0});
        while(queue.size()>0){
            int[] x=queue.poll();
            int row = x[0], col =x[1],sum=sum(row)+sum(col);
            if(row>=m||col>=n||sum>k||visited[row*n+col]==true)continue;
            visited[row*n+col]=true;
            res++;
            queue.add(new int[]{row+1,col});
            queue.add(new int[]{row,col+1});
        }
        return res;
    }

    /**
     * 计算和
     *
     * @param m
     * @return
     */
    public int sum(int m) {
        int sum = 0;
        while (m != 0) {
            sum += m % 10;
            m /= 10;
        }
        return sum;
    }

3、剪绳子

3.1 题目描述:

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

3.2 题解

3.2.1 找规律

找出最大值:

3:2x1=2;4:2x2=4;
5:3x2=6;6:3x3=9;
7:3x2x2=12;8::3x3x2=18
9:3x3x3=27;10:3x3x2x2=36;
由以上可得出,大于3的数的最大值都是由2和3相乘所得;因此只要得出每个数可分为的3和2的个数即可


  public int cuttingRope(int n) {
        if(n <= 3) return n - 1;
        else {
            int k = (n % 3 == 0 ? (n / 3) : ((n - 2) / 3));//k为3的个数
            int j = (n + 2) / 3-k;//j为2的个数
            int mul = 1;
            while (k >0) {
                mul*=3;
                k--;
            }
            while(j>0){
                mul*=2;
                j--;
            }
            return mul;
        }
    }
3.2.2 贪心算法
 public int cuttingRope(int n) {
        if(n <= 3) return n - 1;
        long res=1L;
        //贪心算法,优先切三,其次切二
        while(n>4){
            res=res*3;
            n-=3;
        }
        //出来循环只有三种情况,分别是n=2、3、4
        return res*n;
    }
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页