注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7
思路:因为前序遍历为根左右。 中序遍历为左根右。
所以前序遍历的第一个元素为重建的二叉树的根节点的值。
遍历中序遍历,直到找到和根节点值相同的位置。则此元素左边的都是根节点的左子树的元素,右边的都是根节点右子树的元素。
通过递归很容易求出解。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder.length == 0 || inorder == null || inorder.length == 0 || preorder.length != inorder.length) {
return null;
}
Map map = new HashMap<>();
for(int i=0;i map) {
//递归的第一步:递归终止条件,避免死循环
if (pStart > pEnd || iStart > iEnd) {
return null;
}
//重建根节点
TreeNode treeNode = new TreeNode(preorder[pStart]);
int index = 0; //index找到根节点在中序遍历的位置
index= map.get(preorder[pStart])-iStart;
//重建左子树
treeNode.left = help(preorder, pStart + 1, pStart + index, inorder, iStart, iStart + index - 1,map);
//重建右子树
treeNode.right = help(preorder, pStart + index + 1, pEnd, inorder, iStart + index + 1, iEnd,map);
return treeNode;
}
}
给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。
示例 1:
输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出: 2
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回2。
示例 2:
输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出: 1
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。
思路:该题类似于图的遍历,每次从一个节点开始,进行深度搜索,直到走到尽头,利用一个数组来记录已经加入的小朋友,直到所以小朋友都已被遍历到,结束搜索
class Solution {
public int findCircleNum(int[][] M) {
int[] visited=new int[M.length];
int cnt=0;
for(int i=0;i
两个相邻元素间的距离为 1 。
示例 1:
输入:
0 0 0
0 1 0
0 0 0
输出:
0 0 0
0 1 0
0 0 0
示例 2:
输入:
0 0 0
0 1 0
1 1 1
输出:
0 0 0
0 1 0
1 2 1
class Solution {
public int[][] updateMatrix(int[][] matrix) {
// 首先将所有的 0 都入队,并且将 1 的位置设置成 -1,表示该位置是 未被访问过的 1
Queue queue = new LinkedList<>();
int m = matrix.length, n = matrix[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == 0) {
queue.offer(new int[] {i, j});
} else {
matrix[i][j] = -1;
}
}
}
int[] dx = new int[] {-1, 1, 0, 0};
int[] dy = new int[] {0, 0, -1, 1};
while (!queue.isEmpty()) {
int[] point = queue.poll();
int x = point[0], y = point[1];
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
// 如果四邻域的点是 -1,表示这个点是未被访问过的 1
// 所以这个点到 0 的距离就可以更新成 matrix[x][y] + 1。
if (newX >= 0 && newX < m && newY >= 0 && newY < n
&& matrix[newX][newY] == -1) {
matrix[newX][newY] = matrix[x][y] + 1;
queue.offer(new int[] {newX, newY});
}
}
}
return matrix;
}
}
给定一个代表游戏板的二维字符矩阵。 ‘M’ 代表一个未挖出的地雷,‘E’ 代表一个未挖出的空方块,‘B’ 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字(‘1’ 到 ‘8’)表示有多少地雷与这块已挖出的方块相邻,‘X’ 则表示一个已挖出的地雷。
现在给出在所有未挖出的方块中(‘M’或者’E’)的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板:
如果一个地雷(‘M’)被挖出,游戏就结束了- 把它改为 ‘X’。
如果一个没有相邻地雷的空方块(‘E’)被挖出,修改它为(‘B’),并且所有和其相邻的方块都应该被递归地揭露。
如果一个至少与一个地雷相邻的空方块(‘E’)被挖出,修改它为数字(‘1’到’8’),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回面板。
示例 1:
输入:
[[‘E’, ‘E’, ‘E’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘M’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘E’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘E’, ‘E’, ‘E’]]
Click : [3,0]
输出:
[[‘B’, ‘1’, ‘E’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘M’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘1’, ‘1’, ‘B’],
[‘B’, ‘B’, ‘B’, ‘B’, ‘B’]]
class Solution {
int[] dx={-1,-1,-1,0,1,1,1,0};
int[] dy={-1,0,1,1,1,0,-1,-1};
public char[][] updateBoard(char[][] board, int[] click) {
int x=click[0];
int y=click[1];
if(board[x][y]=='M')
{
board[x][y]='X';
return board;
}
dfs(board,x,y);
return board;
}
public void dfs(char[][] board,int x,int y){
if(board[x][y]!='E')
return;
int cnt=0;
for(int i=0;i<8;i++){
int a=x+dx[i];
int b=y+dy[i];
if(a>=0&&a=0&&b=0&&a=0&&b
示例:
输入:
1
/ \
3 2
/ \ \
5 3 9
输出: [1, 3, 9]
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List largestValues(TreeNode root) {
//层序遍历
List ans = new ArrayList<>();
List list = new ArrayList<>();
if(root==null)
return ans;
int cnt=0;
int max=Integer.MIN_VALUE;
list.add(root);
while(list.size()!=0){
if(cnt==0){
ans.add(max);
max=Integer.MIN_VALUE;
cnt=list.size();
}
TreeNode tmp=list.remove(0);
max=Math.max(max,tmp.val);
if(tmp.left!=null)
list.add(tmp.left);
if(tmp.right!=null)
list.add(tmp.right);
cnt--;
}
ans.remove(0);
ans.add(max);
return ans;
}
}
在形式上,对于每个房间 i 都有一个钥匙列表 rooms[i],每个钥匙 rooms[i][j] 由 [0,1,…,N-1] 中的一个整数表示,其中 N = rooms.length。 钥匙 rooms[i][j] = v 可以打开编号为 v 的房间。
最初,除 0 号房间外的其余所有房间都被锁住。
你可以自由地在房间之间来回走动。
如果能进入每个房间返回 true,否则返回 false。
示例 1:
输入: [[1],[2],[3],[]]
输出: true
解释:
我们从 0 号房间开始,拿到钥匙 1。
之后我们去 1 号房间,拿到钥匙 2。
然后我们去 2 号房间,拿到钥匙 3。
最后我们去了 3 号房间。
由于我们能够进入每个房间,我们返回 true。
示例 2:
输入:[[1,3],[3,0,1],[2],[0]]
输出:false
解释:我们不能进入 2 号房间。
利用一个数组来记录已访问过的房间,初始标记0号下标为true,然后进行dfs,如果该房间已访问过,则返回,否则将该房间标记为已访问,并且拿着该房间内有的钥匙访问能访问的房间,直至结束,最后遍历一次数组,若发现有为访问的房间,则返回false,否则返回true
class Solution {
public boolean canVisitAllRooms(List> rooms) {
boolean[] visited = new boolean[rooms.size()];
visited[0]=true;
for(int i:rooms.get(0)){
dfs(visited,rooms,i);
}
for(boolean visit:visited){
if(!visit){
return false;
}
}
return true;
}
public void dfs(boolean[] visited,List> rooms,int key){
if(visited[key]==true){
return;
}
visited[key]=true;
for(int j:rooms.get(key)){
dfs(visited,rooms,j);
}
}
}