每日三刷,剑指千题
计划简介:
- 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
- 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
- 每日中午进行编码,时间控制在一小时之内。
- 下班前半小时进行整理总结,并发布到掘金每日更文活动。
说明:
- 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
- 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
- 刷题过程中整理相似题型,刷题模板。
- 目前进度 133/1000 。
[剑指 Offer 54]二叉搜索树的第k大节点
给定一棵二叉搜索树,请找出其中第 k
大的节点的值。
示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
输出: 4
解析
简单思路就是遍历再排序,能过,但效率不高。
仔细一看,忽略了二叉搜索树这一条件,也就是说按照中序遍历,二叉树是按升序排好序的。
但只需中序倒序遍历即可,同时 k-- ,当 k=0 时,即找到答案。
这样的好处可以提前结束遍历。
Code
class Solution {
List ans = new ArrayList<Integer>();
public int kthLargest(TreeNode root, int k) {
traverse(root);
Collections.sort(ans);
return (int) ans.get(ans.size() - k);
}
private void traverse(TreeNode root) {
if (root != null) {
ans.add(root.val);
traverse(root.left);
traverse(root.right);
}
}
}
class Solution {
int res;
int index = 0; //计数器
public int kthLargest(TreeNode root, int k) {
dfs(root, k);
return res;
}
void dfs(TreeNode root, int k) {
if (root == null) return;
dfs(root.right, k); //右
index++;
if (k == index) res = root.val; //根
dfs(root.left, k); //左
}
}
[623]在二叉树中增加一行
给定一个二叉树的根 root
和两个整数 val
和 depth
,在给定的深度 depth
处添加一个值为 val
的节点行。
注意,根节点 root
位于深度 1
。
加法规则如下:
- 给定整数
depth
,对于深度为depth - 1
的每个非空树节点cur
,创建两个值为val
的树节点作为cur
的左子树根和右子树根。 cur
原来的左子树应该是新的左子树根的左子树。cur
原来的右子树应该是新的右子树根的右子树。- 如果
depth == 1
意味着depth - 1
根本没有深度,那么创建一个树节点,值val
作为整个原始树的新根,而原始树就是新根的左子树。
示例 1:
输入: root = [4,2,6,3,1,5], val = 1, depth = 2
输出: [4,1,1,2,null,null,6,3,1,5]
解析
看着很复杂,实际就是层序遍历的一个变形,试着写了一下,竟然超过100%,牛批!
Code
class Solution {
public TreeNode addOneRow(TreeNode root, int val, int depth) {
if (depth == 1){
return new TreeNode(val,root,null);
}
int index = 1;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int n = queue.size();
for (int i = 0; i < n; i++) {
TreeNode node = queue.poll();
// 拼接处理
if (index == depth - 1){
TreeNode left = node.left;
TreeNode right = node.right;
node.left = new TreeNode(val,left,null);
node.right = new TreeNode(val,null,right);
}else {
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
}
// 没有break,效率也很高
index++;
}
return root;
}
}
[563]二叉树的坡度
给你一个二叉树的根节点 root
,计算并返回 整个树 的坡度 。
一个树的 节点的坡度 定义即为,该节点左子树的节点之和和右子树节点之和的 差的绝对值 。如果没有左子树的话,左子树的节点之和为 0 ;没有右子树的话也是一样。空结点的坡度是 0 。
整个树 的坡度就是其所有节点的坡度之和。
示例 1:
输入:root = [1,2,3]
输出:1
解释:
节点 2 的坡度:|0-0| = 0(没有子节点)
节点 3 的坡度:|0-0| = 0(没有子节点)
节点 1 的坡度:|2-3| = 1(左子树就是左子节点,所以和是 2 ;右子树就是右子节点,所以和是 3 )
坡度总和:0 + 0 + 1 = 1
解析
看了题解是明白了,可自己还是想不起来,还得练。
Code
class Solution {
int ans = 0;
public int findTilt(TreeNode root) {
dfs(root);
return ans;
}
int dfs(TreeNode root){
if (root==null)return 0;
int l = dfs(root.left);
int r = dfs(root.right);
ans += Math.abs(r-l);
return root.val + l+r;
}
}
\