- 写于2019年6月10日(完成了top中所有的
easy
)
543. 二叉树的直径
① 题目描述
中文描述:https://leetcode-cn.com/problems/diameter-of-binary-tree/
② 二叉树求深度的变种
- 之前,求
二叉树的深度
是从根节点开始,递归得到其左子树、右子树的深度,然后选其中的较大者加1,便是二叉树的深度。其实,就是二叉树的层次或高度
。 - 现在求二叉树的直径,可能是包含根节点,也可能在其左子树或右子树中找到直径。而且直径不是节点个数,而是节点之间的边数,即
节点个数-1
。 - 如果通过求二叉树的深度,获得的左右子树的深度,直接相加便是包含根节点的树的直径。
- 代码如下,运行时间
9ms
:
public int diameterOfBinaryTree(TreeNode root) {
if (root == null) {
return 0;
}
int left1 = 0, left2 = 0, right1 = 0, right2 = 0;
left1 = maxDepth(root.left);
right1 = maxDepth(root.right);
if (root.left != null) {// 包含左孩子的最大直径
left2 = diameterOfBinaryTree(root.left);
}
if (root.right != null) {// 包含右孩子的最大直径
right2 = diameterOfBinaryTree(root.right);
}
return Math.max(Math.max(left1 + right1, left2), right2);
}
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
581. 最短无序连续子数组
① 题目描述
中文题目:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/
② 自己的想法:从前往后找start,从后往前找end
- 如果,从当前数开始直到数组末尾,如果后面的数都
大于等于
当前数,则继续往后查找start
。否则,当前数便是无序数组的起始数。 - 如果,从当前数开始直到数组头部,如果前面的数都
小于等于
当前数,则继续往前查找end
。否则,当前数便是无序数组的最后一个数。 - 代码如下,运行时间
73ms
:
public int findUnsortedSubarray(int[] nums) {
int start = 0;
int end = -1;// 避免整个数组没有无序子数组
for (int i = 0; i < nums.length - 1; i++) {
boolean flag = false;
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] < nums[i]) {
start = i;
flag = true;
break;
}
}
if (flag) {// 第一次出现非升序的下标便是整个需要排序的子数组的start,找到便退出
break;
}
}
for (int i = nums.length - 1; i > 0; i--) {
boolean flag = false;
for (int j = i - 1; j >= 0; j--) {
if (nums[j] > nums[i]) {// 第一次出现非降序的下标便是整个需要排序的子数组的end,找到便退出
end = i;
flag = true;
break;
}
}
if (flag) {
break;
}
}
return end - start + 1;
}
③ 先排序再比较
- 将数组复制到新的数组中,对新数组进行排序后,从前往后比较,找出start;从后往前比较找出end。
- 如果start和end都为0,说明原始数组是全局有序的;否则,返回
end - start + 1
。 - 代码如下,运行时间
7ms
:
public int findUnsortedSubarray(int[] nums) {
int[] copy = new int[nums.length];
int start = 0;
int end = 0;
System.arraycopy(nums, 0, copy, 0, nums.length);
Arrays.sort(copy);
for (int i = 0; i < nums.length; i++) {
if (copy[i] != nums[i]) {
start = i;
break;
}
}
for (int i = nums.length - 1; i >= 0; i--) {
if (copy[i] != nums[i]) {
end = i;
break;
}
}
return (end == 0 && start == 0) ? 0 : (end - start + 1);
}
617. 合并二叉树
① 题目描述
中文题目:https://leetcode-cn.com/problems/merge-two-binary-trees/
② 合并到新的二叉树上
- 除非
root1
和root2
都为null,每次都创建新的节点,并且val要么为0 + t2.val
,要么为t1.val + t2.val
,要么为t1.val + 0
。 - 递归构造新节点的左右孩子,返回新节点。
- 代码如下,运行时间
1ms
:
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) {
return null;
}
TreeNode t3 = new TreeNode((t1 == null ? 0 : t1.val) + (t2 == null ? 0 : t2.val));
t3.left = mergeTrees(t1 == null ? null : t1.left, t2 == null ? null : t2.left);
t3.right = mergeTrees(t1 == null ? null : t1.right, t2 == null ? null : t2.right);
return t3;
}
③ 自己想到的,但未成功实现:合并到t1上
- 合并过程中,将会有四种情况:
①t1 = null
并且t2 = null
,直接返回null
;
② 只有t1 = null
,直接返回t2,将t2整体直接挂到root节点上;
③ 只有t2 = null
,直接返回t1,将t1整体直接挂到root节点上;
④ 都不为null,更新t1的val,并继续查找当前节点的左子树和右子树。 - 其中①和②可以合并为,返回t2。
- 代码如下,运行时间
0ms
:
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if ((t1 == null && t2 == null) || t1 == null) {
return t2;
}
if (t2 == null) {
return t1;
}
t1.val = t1.val + t2.val;
t1.left = mergeTrees(t1.left, t2.left);
t1.right = mergeTrees(t1.right, t2.right);
return t1;
}