[leetcode刷题]——剑指offer

  此篇博客主要记录剑指offer中遇到的不会的题。

 

一、重建二叉树(剑指offer 07)

medium  2021-06-22

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

  解题思路:前序遍历的特点,根节点在第一位; 中序遍历的特点,根节点在中间,左右子树分别在两侧。

    可以先利用前序遍历找出根节点,然后递归寻找左右子树的根节点。

    这个题我断断续续写了两三天都没写出来,放弃了

  

class Solution {
    private Map<Integer, Integer> indexMap;
    public TreeNode myBuildTree(int[] preorder, int[] inorder, int pre_left, int pre_right, int in_left,
                               int in_right){
        if(pre_left > pre_right){
            return null;
        }
        int pre_root = pre_left; //最左边的序号就是这个子树的根节点的序号
        int in_root = indexMap.get(preorder[pre_root]);//找到中序遍历的根节点
        int left_tree_length = in_root - in_left; //左子树的长度
        TreeNode root = new TreeNode(preorder[pre_root]);
        root.left = myBuildTree(preorder, inorder, pre_left + 1, pre_left + left_tree_length,
                               in_left, in_root - 1);
        root.right = myBuildTree(preorder, inorder,pre_left + left_tree_length + 1, pre_right, 
                                in_root + 1, in_right);
        return root;   
    }   
    
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = preorder.length;
        indexMap = new HashMap<>();
        for(int i = 0; i < n; i++){
            indexMap.put(inorder[i], i);
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
    }
}

 

二、斐波那契数列Ⅰ (剑指offer 10)

easy  2021-07-06

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

  我的写法,使用递归操作,结果超时

class Solution {
    public int fib(int n) {
        if(n == 0){
            return 0;
        }else if(n == 1){
            return 1;
        }else{
            return (fib(n - 1) + fib(n - 2)) % (int)(Math.pow(10, 9) + 7) ;
        }
    }   
}

循环的解法

class Solution {
    public int fib(int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;
        int a = 0;  //后两项
        int b = 1;  //后一项
        int sum = 0;
        for(int i = 2; i <= n; i++){  //从第二项开始到第n项
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }
        return sum;
    }
}

 

三、矩阵中的路径 (剑指offer 12)

(medium)   2021-07-16

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

  回溯问题, 这个题中我写了一个bug, 在回溯问题中,访问标志应该在访问后进行恢复,而不是搜索完再初始化。

class Solution {
    private int m;
    private int n;
    private int[][] directions = {{0,1}, {0, -1}, {1, 0}, {-1, 0}};
    private boolean[][] isVisted;
    public boolean exist(char[][] board, String word) {
        m = board.length;
        n = board[0].length;
        isVisted = new boolean[m][n];
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(seqExit(board, 0, i, j, word) == true){
                    return true;
                }   
                //isVisted = new boolean[m][n]; //不能这里修改
            }
        }
        return false;               
    }
    private boolean seqExit(char[][] board, int seat, int i, int j, String word){
        if(i < 0 || i >= m || j < 0 || j >= n || isVisted[i][j] == true || board[i][j] != word.charAt(seat)){
            return false;
        }
        if(seat == word.length() - 1) return true;
        isVisted[i][j] = true;
        for(int[] dir : directions){
            if(seqExit(board, seat + 1, i + dir[0], j + dir[1], word)){
                return true;
            }
        } 
        isVisted[i][j] = false; //在这里进行访问标志的修改
        return false;
    }
}

 

四、顺时针打印矩阵(剑指offer 29)

(easy)  2021-07-19

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

 

  这个题关键是找好边界条件

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if(matrix.length == 0) return new int[0];
        int l = 0, r = matrix[0].length - 1, t = 0, b = matrix.length - 1, x = 0;
        int[] res = new int[(r + 1) * (b + 1)];
        while(true) {
            for(int i = l; i <= r; i++) res[x++] = matrix[t][i]; // left to right.
            if(++t > b) break;
            for(int i = t; i <= b; i++) res[x++] = matrix[i][r]; // top to bottom.
            if(l > --r) break;
            for(int i = r; i >= l; i--) res[x++] = matrix[b][i]; // right to left.
            if(t > --b) break;
            for(int i = b; i >= t; i--) res[x++] = matrix[i][l]; // bottom to top.
            if(++l > r) break;
        }
        return res;
    }
}

 

posted @ 2021-06-29 11:22  -野比大雄-  阅读(166)  评论(0)    收藏  举报