[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; } }