华为 OD
这几年随着招聘行情的日渐严峻,不少 985 高校出来的学生都开始放宽对"外包"的看法,其中华为 OD 以"待遇断层领先"的姿态成为不少求职者(不得已)的外包首选。
既然如此,我们就好好梳理一下华为 OD 的职级和待遇:
-
13 级:9000 ~ 13000 -
14 级:13000 ~ 17000 -
15 级:17000 ~ 21000 -
16 级:21000 ~ 25000 -
17 级:25000 ~ 32000
除了月薪(base),华为 OD 也是有年终奖的,年终奖和个人绩效挂钩,绩效为 A 可以拿 4 个月年终,绩效为 B 可以拿 2 个月年终,因此华为 OD 年终奖的范围在 2~4 个月。
另外,有意思的是,华为 OD 相比于正式员工更容易获得 A 绩效,但新员工前 6 个月的试用期(工资不打折)默认绩效为 B。
除此以外,还有大家最关心的"加班费"问题。
华为 OD 是有加班费的,加班工资为平时工资的两倍,但每个月的最后一个星期六默认需要加班,若不参加需要额外请假。
至于其他「带薪年假、夜宵、班车、加班打车报销」等福利,也都是和正式员工一致。
综合来看,华为 OD 至少从待遇上要比外面中小厂好上不少。
对此,你怎么看,相比前几年,你对"外包"的看法有发生改变吗?欢迎评论区交流。
...
回归主线。
假期余额不足,来一道高频面试题醒醒脑。
题目描述
平台:LeetCode
题号:692
给一非空的单词列表,返回前 k
个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。
如果不同的单词有相同出现频率,按字母顺序排序。
示例 1:
输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。
注意,按字母顺序 "i" 在 "love" 之前。
示例 2:
输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词,
出现次数依次为 4, 3, 2 和 1 次。
注意:
-
假定 k
总为有效值,1 ≤ k ≤ 集合元素数
。 -
输入的单词均由小写字母组成。
扩展练习:
-
尝试以 时间复杂度和 空间复杂度解决。
哈希表 & 优先队列(堆)
这道题是在「优先队列(堆)」裸题的基础上增加了字典序大小的比较。
相应的,我们不能只根据「词频大小」构建小根堆来获取前 个元素,还需要结合字典序大小来做。
具体的,我们可以使用「哈希表」&「优先队列」进行求解:
-
使用「哈希表」来统计所有的词频 -
构建大小为 按照「词频升序 + (词频相同)字典序倒序」的优先队列: -
如果词频不相等,根据词频进行升序构建,确保堆顶元素是堆中词频最小的元素 -
如果词频相等,根据字典序大小进行倒序构建,结合 可以确保堆顶元素是堆中「词频最小 & 字典序最大」的元素
-
-
对所有元素进行遍历,尝试入堆: -
堆内元素不足 个:直接入堆 -
词频大于堆顶元素:堆顶元素不可能是前 大的元素。将堆顶元素弹出,并将当前元素添加到堆中 -
词频小于堆顶元素;当前元素不可能是前 大的元素,直接丢弃。 -
词频等于堆顶元素:根据当前元素与堆顶元素的字典序大小决定(如果字典序大小比堆顶元素要小则入堆)
-
-
输出堆内元素,并翻转
代码:
class Solution {
public List<String> topKFrequent(String[] words, int k) {
Map<String, Integer> map = new HashMap<>();
for (String w : words) map.put(w, map.getOrDefault(w, 0) + 1);
PriorityQueue<Object[]> q = new PriorityQueue<>(k, (a, b)->{
// 如果词频不同,根据词频升序
int c1 = (Integer)a[0], c2 = (Integer)b[0];
if (c1 != c2) return c1 - c2;
// 如果词频相同,根据字典序倒序
String s1 = (String)a[1], s2 = (String)b[1];
return s2.compareTo(s1);
});
for (String s : map.keySet()) {
int cnt = map.get(s);
if (q.size() < k) { // 不足 k 个,直接入堆
q.add(new Object[]{cnt, s});
} else {
Object[] peek = q.peek();
if (cnt > (Integer)peek[0]) { // 词频比堆顶元素大,弹出堆顶元素,入堆
q.poll();
q.add(new Object[]{cnt, s});
} else if (cnt == (Integer)peek[0]) { // 词频与堆顶元素相同
String top = (String)peek[1];
if (s.compareTo(top) < 0) { // 且字典序大小比堆顶元素小,弹出堆顶元素,入堆
q.poll();
q.add(new Object[]{cnt, s});
}
}
}
}
List<String> ans = new ArrayList<>();
while (!q.isEmpty()) ans.add((String)q.poll()[1]);
Collections.reverse(ans);
return ans;
}
}
C++ 代码:
class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k) {
unordered_map<string, int> map;
for (auto& w : words) map[w]++;
auto comp = [](const pair<int, string>& a, const pair<int, string>& b) {
if (a.first != b.first) return a.first > b.first;
return a.second < b.second;
};
priority_queue<pair<int, string>, vector<pair<int, string>>, decltype(comp)> q(comp);
for (auto& s : map) {
int cnt = s.second;
if (q.size() < k) {
q.push({cnt, s.first});
} else {
if (cnt > q.top().first) {
q.pop();
q.push({cnt, s.first});
} else if (cnt == q.top().first) {
if (s.first.compare(q.top().second) < 0) {
q.pop();
q.push({cnt, s.first});
}
}
}
}
vector<string> ans;
while (!q.empty()) {
ans.push_back(q.top().second);
q.pop();
}
reverse(ans.begin(), ans.end());
return ans;
}
};
-
时间复杂度:使用哈希表统计词频,复杂度为 ;使用最多 个元素维护一个大小为 的堆,复杂度为 ;输出答案复杂度为 (同时 )。整体复杂度为 -
空间复杂度:
最后
巨划算的 LeetCode 会员优惠通道目前仍可用 ~
使用福利优惠通道 leetcode.cn/premium/?promoChannel=acoier,年度会员 有效期额外增加两个月,季度会员 有效期额外增加两周,更有超大额专属 🧧 和实物 🎁 福利每月发放。
我是宫水三叶,每天都会分享算法知识,并和大家聊聊近期的所见所闻。
欢迎关注,明天见。
更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉