[leetcode] 树 -Ⅰ
均为 Simple 难度的水题。
二叉树的中序遍历
题目[94]:给定一个二叉树,返回它的中序 遍历。
解题思路:Too simple.
class Solution
{
public:
vector<int> inorderTraversal(TreeNode *root)
{
return inorderNonRec(root);
vector<int> v;
innerTraversal(root, v);
return v;
}
void innerTraversal(TreeNode *p, vector<int> &v)
{
if (p == nullptr)
return;
innerTraversal(p->left, v);
v.push_back(p->val);
innerTraversal(p->right, v);
}
vector<int> inorderNonRec(TreeNode *root)
{
vector<int> v;
if (root != nullptr)
{
stack<TreeNode *> s;
auto p = root;
while (!s.empty() || p != nullptr)
{
if (p != nullptr)
{
s.push(p);
p = p->left;
}
else
{
p = s.top(), s.pop();
v.push_back(p->val);
p = p->right;
}
}
}
return v;
}
};
相同的树
题目[100]:给定两个二叉树,编写一个函数来检验它们是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例
输入: 1 1
/ \ / \
2 3 2 3
[1,2,3], [1,2,3]
输出: true
解题思路:递归。
#include "leetcode.h"
class Solution
{
public:
bool isSameTree(TreeNode *p, TreeNode *q)
{
return innerCheck(p, q);
}
bool innerCheck(TreeNode *p, TreeNode *q)
{
if ((p == nullptr) ^ (q == nullptr))
return false;
if (p == nullptr && q == nullptr)
return true;
if (p->val != q->val)
return false;
return innerCheck(p->left, q->left) && innerCheck(p->right, q->right);
}
};
对称二叉树
题目[101]:给定一个二叉树,检查它是否是镜像对称的。
示例
input:
1
/ \
2 2
/ \ / \
3 4 4 3
output: true
解题思路:递归。
class Solution
{
public:
bool isSymmetric(TreeNode *root)
{
if (root == nullptr)
return true;
return innerCheck(root->left, root->right);
}
bool innerCheck(TreeNode *p, TreeNode *q)
{
if ((p == nullptr) ^ (q == nullptr))
return false;
if (p == nullptr)
return true;
if (p->val != q->val)
return false;
return innerCheck(p->left, q->right) && innerCheck(p->right, q->left);
}
};
二叉树的最大深度
题目[104]:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
示例
input:
3
/ \
9 20
/ \
15 7
output: 3
解题思路:DFS 。
#define max(a, b) ((a) > (b) ? (a) : (b))
class Solution
{
public:
int maxDepth(TreeNode *root)
{
return dfs(root);
}
int dfs(TreeNode *p)
{
if (p == nullptr)
return 0;
int a = dfs(p->left), b = dfs(p->right);
return max(a, b) + 1;
}
};
值得注意的是,不能 return max(dfs(p->lect), dfs(p->right)) + 1
,因为宏展开后就会执行 4 次 DFS 。
二叉树的层次遍历 II
题目[107]:给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)。
示例
Input:
3
/ \
9 20
/ \
15 7
Output:
[[15,7], [9,20], [3]]
解题思路:使用队列进行层次遍历,同时记下层数,使用 map<int,vector>
记录各个层次的节点。
struct Tuple
{
TreeNode *ptr;
int level;
Tuple(TreeNode *q = nullptr, int l = -1) : ptr(q), level(l) {}
};
class Solution
{
public:
vector<vector<int>> levelOrderBottom(TreeNode *root)
{
if (root == nullptr)
return vector<vector<int>>();
map<int, vector<int>> m;
queue<Tuple> q;
q.push(Tuple(root, 0));
while (!q.empty())
{
Tuple p = q.front();
q.pop();
m[p.level].push_back(p.ptr->val);
if (p.ptr->left)
q.push(Tuple(p.ptr->left, p.level + 1));
if (p.ptr->right)
q.push(Tuple(p.ptr->right, p.level + 1));
}
vector<vector<int>> v;
for (auto x : m)
v.push_back(x.second);
return vector<vector<int>>(v.rbegin(), v.rend());
}
};
将有序数组转换为二叉搜索树
题目[108]:将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
解题思路:二叉搜索树的性质是中序遍历呈升序,所以数组的中间元素 nums[mid]
必然是二叉树的根节点。所以 [start, mid - 1]
是左子树,[mid + 1, end]
是右子树,递归处理。如果数组长度为偶数,中间元素有 2 个,可任意取一个为根节点。
class Solution
{
public:
TreeNode *sortedArrayToBST(vector<int> &nums)
{
TreeNode *root = nullptr;
innerCreate(nums, 0, nums.size() - 1, root);
return root;
}
void innerCreate(vector<int> &v, int start, int end, TreeNode *&p)
{
if (start > end)
return;
int mid = start + (end - start) / 2;
p = new TreeNode(v[mid]);
innerCreate(v, start, mid - 1, p->left);
innerCreate(v, mid + 1, end, p->right);
}
};
平衡二叉树
题目[110]:给定一个二叉树,判断它是否是高度平衡的二叉树。
示例
Input: [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
Output: true
解题思路:
暴力解法
#include <cmath>
class Solution
{
public:
bool isBalanced(TreeNode *root)
{
return forceSolution(root);
}
// brute force solution
bool forceSolution(TreeNode *p)
{
if (p == nullptr)
return true;
bool flag = abs(height(p->left) - height(p->right)) <= 1;
return flag && forceSolution(p->left) && forceSolution(p->right);
}
int height(TreeNode *p)
{
if (p == nullptr)
return 0;
return max(height(p->left), height(p->right)) + 1;
}
};
请注意一点细节,
flag && forceSolution(p->left) && forceSolution(p->right)
效率要比forceSolution(p->left) && forceSolution(p->right) && flag
高。显然,暴力解法对求高度存在需要「冗余」的情况,比如,我们知道
h(left) = height(p->left)
,那么h(p) = h(left) + 1
,但是暴力解法仍然用h(p) = height(p)
。自底向上的递归
返回值表示以
p
为根的子树是否平衡,height
记录以p
为根的子树的高度。bool isBalanced(TreeNode *root)
{
int height = 0;
return innerIsBalanced(root, height);
}
bool innerIsBalanced(TreeNode *p, int &height)
{
if (p == nullptr)
{
height = 0;
return true;
}
int lh = 0, rh = 0;
if (innerIsBalanced(p->left, lh) && innerIsBalanced(p->right, rh) && abs(lh - rh) <= 1)
{
height = max(lh, rh) + 1;
return true;
}
return false;
}
二叉树的最小深度
题目[111]:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
示例
Input:
3
/ \
9 20
/ \
15 7
Output: 2
解题思路:记录每个节点层数的层次遍历(实质上是 BFS)。第一个叶子节点的层数就是答案。
class Solution
{
public:
int minDepth(TreeNode *root)
{
return (root == nullptr) ? 0 : bfs(root);
}
int bfs(TreeNode *root)
{
typedef pair<TreeNode *, int> Node;
queue<Node> q;
q.push(Node(root, 1));
while (!q.empty())
{
auto &node = q.front();
q.pop();
if (node.first->left == nullptr && node.first->right == nullptr)
return node.second;
if (node.first->left != nullptr)
q.push(Node(node.first->left, node.second + 1));
if (node.first->right != nullptr)
q.push(Node(node.first->right, node.second + 1));
}
return -1;
}
};
路径总和
题目[112]:给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
示例
Input: sum = 22
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
Output: true, because sum(5->4->11->2) = 22
解题思路:回溯法。current
记录当前的遍历路径的和。
class Solution
{
public:
bool hasPathSum(TreeNode *root, int sum)
{
bool result = false;
innerSum(root, sum, 0, result);
return result;
}
void innerSum(TreeNode *p, int target, int current, bool &result)
{
if (p == nullptr)
return;
current += p->val;
if (current == target && p->left == nullptr && p->right == nullptr)
{
result = true;
return;
}
innerSum(p->left, target, current, result);
if (!result)
innerSum(p->right, target, current, result);
}
};
翻转二叉树
题目[226]:翻转一棵二叉树。
示例
Input:
4
/ \
2 7
/ \ / \
1 3 6 9
Output:
4
/ \
7 2
/ \ / \
9 6 3 1
解题思路:对每个节点执行 swap(p->left, p->right)
。TreeNode* &p
表示的是指针的引用。
class Solution
{
public:
TreeNode *invertTree(TreeNode *root)
{
if (root != nullptr)
innerInvert(root->left, root->right);
return root;
}
void innerInvert(TreeNode *&l, TreeNode *&r)
{
auto p = l;
l = r;
r = p;
if (l != nullptr)
innerInvert(l->left, l->right);
if (r != nullptr)
innerInvert(r->left, r->right);
}
};
二叉搜索树的最近公共祖先
题目[235]:给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
示例
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
解题思路:利用二叉搜索树的性质,左子树 < 根 < 右子树。那么:
p.val < root.val && q.val < root.val
:在左子树搜索。p.val > root.val && q.val < root.val
:在右子树搜索。- 其他情况:
root
就是公共祖先。
递归解法
TreeNode *lca(TreeNode *root, TreeNode *p, TreeNode *q)
{
if (p->val < root->val && q->val < root->val)
return lca(root->left, p, q);
else if (p->val > root->val && q->val > root->val)
return lca(root->right, p, q);
else
return root;
}
非递归解法
TreeNode *lca2(TreeNode *root, TreeNode *p, TreeNode *q)
{
auto node = root;
while (node != nullptr)
{
if (p->val < node->val && q->val < node->val)
node = node->left;
else if (p->val > node->val && q->val > node->val)
node = node->right;
else
break;
}
return node;
}
二叉树的所有路径
题目[257]:给定一个二叉树,返回所有从根节点到叶子节点的路径。
示例
输入:
1
/ \
2 3
\
5
输出: ["1->2->5", "1->3"]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
解题思路:显而易见的回溯法(实际上也是二叉树的遍历),如果找到叶子节点,说明是一个完整的路径。
#include "leetcode.h"
class Solution
{
public:
vector<string> result;
vector<string> binaryTreePaths(TreeNode *root)
{
if (root != nullptr)
preorder(root, "");
return result;
}
void preorder(TreeNode *p, string s)
{
bool l = (p->left != nullptr);
bool r = (p->right != nullptr);
if (l || r)
s += to_string(p->val) + "->";
else if (!l && !r)
{
s += to_string(p->val);
result.push_back(s);
return;
}
if (l)
preorder(p->left, s);
if (r)
preorder(p->right, s);
}
};
左叶子之和
题目[404]:计算给定二叉树的所有左叶子之和。
示例
3
/ \
9 20
/ \
15 7
在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
解题思路:遍历过程使用一个 flag
来表示本次节点是否为左子树。如果既是左子树,又是叶子节点,就是要累加的节点。
#include "leetcode.h"
class Solution
{
public:
int sum = 0;
int sumOfLeftLeaves(TreeNode *root)
{
if (root != nullptr)
preorder(root, false);
return sum;
}
void preorder(TreeNode *root, bool isLeft)
{
bool l = (root->left != nullptr);
bool r = (root->right != nullptr);
if (isLeft && !l && !r)
sum += root->val;
if (l)
preorder(root->left, true);
if (r)
preorder(root->right, false);
}
};
⭐ 路径总和 III
题目[437]:给定一个二叉树,它的每个结点都存放着一个整数值。找出路径和等于给定数值的路径总数。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ \ \
3 2 11
/ \ \
3 -2 1
返回 3。和等于 8 的路径有:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
解题思路:将二叉树的每一个完整路径看作是一个数组 nums
(假设第一个元素是 nums[1]
),那么本题就是要找到 sum(i, j) = sum
的下标 i 和 j 。
为此,使用一个数组 v
,v[0] = 0
,v[i]
表示 sum(nums[1] ... nums[i])
,即 nums
前 i 个元素的和。那么 sum(nums[i] ... nums[j]) = v[j] - v[i - 1]
。
使用先序遍历每一个从根到叶子的路径。
class Solution
{
public:
int result = 0;
int pathSum(TreeNode *root, int sum)
{
if (root == nullptr)
return 0;
int d = depth(root);
vector<int> v(d + 1);
preorder(1, v, root, sum);
return result;
}
int depth(TreeNode *p)
{
if (p == nullptr)
return 0;
return max(depth(p->left), depth(p->right)) + 1;
}
void preorder(int idx, vector<int> &v, TreeNode *p, const int sum)
{
if (p == nullptr)
return;
v[idx] = v[idx - 1] + p->val;
for (int i = 0; i < idx; i++)
{
if (v[idx] - v[i] == sum)
result++;
}
preorder(idx + 1, v, p->left, sum);
preorder(idx + 1, v, p->right, sum);
}
};
⭐二叉搜索树中的众数
题目[501]:给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
示例
Input:
1
\
2
/
2
Output: [2]
解题思路:利用BST的性质,中序遍历为升序序列。current
记录当前数字 number
出现的次数,last
记录上一次找到的「候选众数」出现的次数。
class Solution
{
public:
vector<int> v;
int current = 0;
int last = 0;
int number = 0x80000000;
vector<int> findMode(TreeNode *root)
{
if (root != nullptr)
inorder(root);
return v;
}
void inorder(TreeNode *p)
{
if (p == nullptr)
return;
inorder(p->left);
if (last == 0)
last = 1;
if (p->val != number)
current = 0;
number = p->val;
current++;
if (current == last)
v.push_back(number);
if (current > last)
{
last = current;
v.clear(), v.push_back(number);
}
inorder(p->right);
}
};
二叉搜索树的最小绝对差
题目[530]:给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
示例
输入:
1
\
3
/
2
输出:1
解释:最小绝对差为 1,其中 2 和 1 的差的绝对值为 1(或者 2 和 3)。
解题思路:BST中序遍历呈升序。
#include "leetcode.h"
class Solution
{
public:
int result = 0x7ffffff;
int pre = 0x7fffffff;
int getMinimumDifference(TreeNode *root)
{
inorder(root);
return result;
}
void inorder(TreeNode *p)
{
if (p == nullptr)
return;
inorder(p->left);
result = min(result, abs(p->val - pre));
pre = p->val;
inorder(p->right);
}
};
把二叉搜索树转换为累加树
题目[538]:给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。
示例
输入: 原始二叉搜索树:
5
/ \
2 13
输出: 转换为累加树:
18
/ \
20 13
解题思路:逆中序遍历 BST 。
class Solution
{
public:
int sum = 0;
TreeNode *convertBST(TreeNode *root)
{
postorder(root);
return root;
}
void postorder(TreeNode *p)
{
if (p == nullptr)
return;
postorder(p->right);
sum += p->val;
p->val = sum;
postorder(p->left);
}
};
⭐二叉树的直径
题目[534]:给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
示例
Input:
1
/ \
2 3
/ \
4 5
Output: 3
解题思路:所谓直径,就是二叉树中任意路径上的节点数减一。
对于二叉树中的每个节点 node
,以 node
为根的子树,其直径为 depth(node.left) + depth(node.right)
。
自顶向下的递归
int result = 0;
int diameterOfBinaryTree(TreeNode *root)
{
preorder(root);
return result;
} int depth(TreeNode *p)
{
return p == nullptr ? 0 : max(depth(p->left), depth(p->right)) + 1;
} void preorder(TreeNode *p)
{
if (p == nullptr)
return;
result = max(result, depth(p->left) + depth(p->right));
preorder(p->left);
preorder(p->right);
}
自底向上的递归
显然,对每个节点都调用一次
depth
函数,有很多冗余的遍历。求出每个节点的高度,实际上只需要一次自底向上的遍历。因为depth(p) = max(depth(p.left), depth(p.right)) + 1
。因此可使用后序遍历。int result = 0;
int diameterOfBinaryTree(TreeNode *root)
{
int height = 0;
bottom2top(root, height);
return result;
}
void bottom2top(TreeNode *p, int &height)
{
if (p == nullptr)
{
height = 0;
return;
}
int l = height, r = height;
bottom2top(p->left, l);
bottom2top(p->right, r);
height = max(l, r) + 1;
result = max(result, l + r);
}
二叉树的坡度
题目[563]:给定一个二叉树,计算整个树的坡度。一个树的节点的坡度定义即为,该节点左子树的结点之和和右子树结点之和的差的绝对值。空结点的的坡度是0。整个树的坡度就是其所有节点的坡度之和。
示例
输入:
1
/ \
2 3
输出: 1
解释:
结点的坡度 2 : 0
结点的坡度 3 : 0
结点的坡度 1 : |2-3| = 1
树的坡度 : 0 + 0 + 1 = 1
解题思路:实际上要解决的问题是怎么求出每个子树的和。显然还是采取自底向上的后序遍历。
class Solution
{
public:
int tilt = 0;
int findTilt(TreeNode *root)
{
int sum = 0;
postorder(root, sum);
return tilt;
}
void postorder(TreeNode *p, int &sum)
{
if (p == nullptr)
{
return;
}
int l = sum, r = sum;
postorder(p->left, l);
postorder(p->right, r);
sum += p->val + l + r;
tilt += abs(l - r);
}
};
另一个树的子树
题目[572]:给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
解题思路:暴力解法。先实现 isSame(s, t)
判断 s
和 t
是否完全相等,再遍历 s
的每一个节点 p
,判断 isSame(p, t)
。
class Solution
{
public:
bool isSubtree(TreeNode *s, TreeNode *t)
{
if (s == nullptr)
return t == nullptr;
queue<TreeNode *> q;
q.push(s);
while (!q.empty())
{
auto p = q.front();
q.pop();
if (isSame(p, t))
return true;
if (p->left != nullptr)
q.push(p->left);
if (p->right != nullptr)
q.push(p->right);
}
return false;
}
bool isSame(TreeNode *s, TreeNode *t)
{
if ((s == nullptr) ^ (t == nullptr))
return false;
if (s == nullptr && t == nullptr)
return true;
return (s->val == t->val) && isSame(s->left, t->left) && isSame(s->right, t->right);
}
};
[leetcode] 树 -Ⅰ的更多相关文章
- LeetCode树专题
LeetCode树专题 98. 验证二叉搜索树 二叉搜索树,每个结点的值都有一个范围 /** * Definition for a binary tree node. * struct TreeNod ...
- leetcode 树类型题
树的测试框架: // leetcodeTree.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream& ...
- leetcode: 树
1. sum-root-to-leaf-numbers Given a binary tree containing digits from0-9only, each root-to-leaf pat ...
- Leetcode 树(102, 637)
637: 二叉树的层平均值 给定一个非空二叉树,返回一个由每层节点平均值组成的数组: https://leetcode-cn.com/problems/average-of-levels-in-bin ...
- leetcode树专题894.897,919,951
满二叉树是一类二叉树,其中每个结点恰好有 0 或 2 个子结点. 返回包含 N 个结点的所有可能满二叉树的列表. 答案的每个元素都是一个可能树的根结点. 答案中每个树的每个结点都必须有 node.va ...
- leetcode 树的锯齿形状遍历
二叉树的锯齿形层次遍历 给定一个二叉树,返回其节点值的锯齿形层次遍历.(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行). 例如:给定二叉树 [3,9,20,null,n ...
- [leetcode] 树(Ⅱ)
All questions are simple level. Construct String from Binary Tree Question[606]:You need to construc ...
- Leetcode 树 Populating Next Right Pointers in Each Node II
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Populating Next Right Pointers in Each Node II ...
- leetcode树相关
目录 144前序遍历 94中序遍历(98验证二叉搜索树.230二叉搜索树中第K小的元素) 145后序遍历 102/107层次遍历(104二叉树最大深度.103 105从前序与中序遍历序列构造二叉树 1 ...
随机推荐
- Git将文件上传至Github过程
1.安装Git工具(在这里就不多说了) 2.我们需要先创建一个本地的版本库(其实也就是一个文件夹). 你可以直接在桌面右击新建文件夹,也可以右击打开Git bash命令行窗口通过命令来创建. 现在我通 ...
- JavaScript的函数(三)
函数也是对象,拥有属性和方法,就类似普通对象那样.1,length属性 arguments.lenght 表示传入实参的个数. 函数的length属性时只读属性,代表形参的个数.可以用argument ...
- 【Python challenge】通关代码及攻略(0-11)
前言: 最近找到一个有关python的游戏闯关,这是游戏中的思考及通关攻略 最开始位于:http://www.pythonchallenge.com/pc/def/0.html 第0关 题目分析 提示 ...
- Java Grammar(二):运算符
运算符简介 计算机自打诞生以来,用作最多的就是进行计算,而计算离不开运算符,所以运算符在我们的Java语言中的地位举足轻重,我们现在就来了解一下Java给我们提供的运算符. 从运算的元素的个数来区分, ...
- 【Weiss】【第03章】练习3.17:懒惰删除
[练习3.17] 不同于我们已经给出的删除方法,另一种是使用懒惰删除的方法. 为了删除一个元素,我们只标记上该元素被删除的信息(使用一个附加的位域). 表中被删除和非被删除的元素个数作为数据结构的一部 ...
- Deepin中安装使用好用的字典GoldenDict
2020-03-21 23:08:17 不说废话直接来安装步骤: 打开Deepin的应用商店,输入GoldenDict查找: 找到后点击安装,然后等待一小会,电脑提示音告诉你已经安装完成: 然后再 ...
- 源码解读 Golang 的 sync.Map 实现原理
简介 Go 的内建 map 是不支持并发写操作的,原因是 map 写操作不是并发安全的,当你尝试多个 Goroutine 操作同一个 map,会产生报错:fatal error: concurrent ...
- 图解I/O模型
本文带你鸟瞰I/O模型全貌,希望可以让你对I/O模型有一个直观的认识 什么是I/O?I/O的过程?同步阻塞 I/O同步非阻塞 I/OI/O多路复用异步I/O 什么是I/O? I/O就是计算机内 ...
- Journal of Proteomics Research | 利用混合蛋白质组模型对MBR算法中错误转移鉴定率的评估
题目:Evaluating False Transfer Rates from the Match-between-Runs Algorithm with a Two-Proteome Model 期 ...
- 目标检测 | RetinaNet:Focal Loss for Dense Object Detection
论文分析了one-stage网络训练存在的类别不平衡问题,提出能根据loss大小自动调节权重的focal loss,使得模型的训练更专注于困难样本.同时,基于FPN设计了RetinaNet,在精度和速 ...