小米
最近,新晋成为万亿公司的小米,又搞了个大新闻。
3 月 18 日,小米集团发布公告,披露了最新股权激励计划。此项计划覆盖 3877 名员工及供应商,涉及 8344 万股(约合人民币 45 亿),其中供应商获授 17.1 万股。主体激励股份行权价为零对价,但股票归属期最长跨越十年(2025~2035)。
这里面信息量很多,而且有不少很有争议(当然也可以说是"创新"),带大家解读一下。
首先创新点之一,是股权激励对象包含了供应商。
8344 万股,覆盖员工和供应商,虽然供应商仅获授其中的 17.1 万股(占比 0.2%),主要的激励对象还是那 3877 名员工(占比 99.8%),但并不影响这成为"小米激励计划"的创新点之一。
众所周知,小米是一家极其强调"性价比"的(制造业+互联网)公司,于是"供应商管理"也成了小米核心护城河之一。
这次把供应商纳入到激励计划当中,一定程度是小米在对外传递善意。表示自己会把强调"长期合作"的供应商视为集团的一份子。
别看这 17.1 万股,占比只有 0.2%,看着不多,但按现价折算,也有 900 万了。更重要的是,这只是开头,将来股价还会上升(大概率),激励计划也还会追加。甚至更更重要的是,供应商和其他友商合作,并没有这项福利待遇,所以是纯纯的增量。未来这些进入了侯选名单的供应商,会进一步倾向于选择小米合作,我一点都不会感到奇怪。
这项激励计划的另外一个创新点,是「零对价」但「归属期最长跨越十年(2025~2035)」。
所谓的零对价,就是字面意思,这些期权的发放,不需要花一分钱来认购,这和其他公司的「需要花钱认购股权,才能参与分红」的方式不同,对被激励对象来说,是真正的"零成本"。
但与之相对应的,是严格的规则,除了「超长的归属期」以外,还有「重大违规强制收回的回补政策」。
这其实,还是在强调"长期关系"。
传统的互联网公司,通常归属年限都在 3~5 年,而且最近几年,不少大厂还有"加快归属"的趋势,例如字节跳动和阿里巴巴,这次小米却反其道而行之。
你很难说它是在回归本质(强调长期),还是单纯的加大难度(必然只有少数人能拿满)。
对此,你怎么看?你会认同小米这次的激励计划吗?欢迎评论区交流。
...
回归主题。
周末,接着来轻松算法题。
题目描述
平台:LeetCode
题号:671
给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。
如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。
更正式地说,root.val = min(root.left.val, root.right.val)
总成立。
给出这样的一个二叉树,你需要输出所有节点中的第二小的值。
如果第二小的值不存在的话,输出 -1。
示例 1:
输入:root = [2,2,5,null,null,5,7]
输出:5
解释:最小的值是 2 ,第二小的值是 5 。
示例 2:
输入:root = [2,2,2]
输出:-1
解释:最小的值是 2, 但是不存在第二小的值。
提示:
- 树中节点数目在范围 内
- 对于树中每个节点
root.val = min(root.left.val, root.right.val)
树的遍历
一个朴素的做法是,直接对树进行遍历(广度 & 深度),使用 HashSet
进行存储,得到所有去重后的节点大小。
然后找次小值的方式有多种:可以通过排序找次小值,复杂度为 ;也可以使用经典的两个变量 & 一次遍历的方式,找到次小值,复杂度为 。
Java 代码:
class Solution {
Set<Integer> set = new HashSet<>();
public int findSecondMinimumValue(TreeNode root) {
dfs(root);
if (set.size() < 2) return -1;
int first = Integer.MAX_VALUE, second = Integer.MAX_VALUE;
for (int i : set) {
if (i <= first) {
second = first;
first = i;
} else if (i <= second) {
second = i;
}
}
return second;
}
void dfs(TreeNode root) {
if (root == null) return;
set.add(root.val);
dfs(root.left);
dfs(root.right);
}
}
Java 代码:
class Solution {
Set<Integer> set = new HashSet<>();
public int findSecondMinimumValue(TreeNode root) {
bfs(root);
if (set.size() < 2) return -1;
int first = Integer.MAX_VALUE, second = Integer.MAX_VALUE;
for (int i : set) {
if (i <= first) {
second = first;
first = i;
} else if (i <= second) {
second = i;
}
}
return second;
}
void bfs(TreeNode root) {
Deque<TreeNode> d = new ArrayDeque<>();
d.addLast(root);
while (!d.isEmpty()) {
TreeNode poll = d.pollFirst();
set.add(poll.val);
if (poll.left != null) d.addLast(poll.left);
if (poll.right != null) d.addLast(poll.right);
}
}
}
- 时间复杂度:树的搜索复杂度为 ,通过线性遍历找次小值,复杂度为 。整体复杂度为
- 空间复杂度:
递归
解法一显然没有利用到本题核心条件 :「root.val = min(root.left.val, root.right.val)
」和「每个子节点数量要么是 0
要么是 2
」。
我们可以设计如下递归函数,含义为 从 root
为根的树进行搜索,找到值比 cur
大的最小数。然后使用全局变量 ans
存储答案。
void dfs(TreeNode root, int cur)
那么最终搜索范围为 dfs(root, root.val)
,这是因为 性质 root.val = min(root.left.val, root.right.val)
,即最小值会不断往上传递,最终根节点必然是全局最小值。
然后再结合「每个子节点数量要么是 0
要么是 2
」,我们可以特判一下 ans
是否为第一次赋值,如果给 ans
赋了新值或者更新了更小的 ans
,则不再需要往下搜索了。
Java 代码:
class Solution {
int ans = -1;
public int findSecondMinimumValue(TreeNode root) {
dfs(root, root.val);
return ans;
}
void dfs(TreeNode root, int cur) {
if (root == null) return ;
if (root.val != cur) {
if (ans == -1) ans = root.val;
else ans = Math.min(ans, root.val);
return ;
}
dfs(root.left, cur);
dfs(root.right, cur);
}
}
- 时间复杂度:
- 空间复杂度:忽略递归带来的空间开销。复杂度为