lucifer

华为这波太猛了,多人被开除

  |  

最近华为内部掀起了一场堪称“史诗级”的反腐风暴,目标直指招聘环节的黑产链。消息一出,圈内炸了锅——原来上班还能“付费入场”?这波操作不仅暴露了内部管理的漏洞,还把一条完整的腐败产业链扒得底朝天。金额巨大,成都基地中层被带走,150 人单日清退,零补偿+“诚信污点”追责,华为这次出手,比字节的清理还狠三分。

黑产链有多夸张?

据脉脉上的爆料,这次的招聘腐败简直是“明码标价”的生意。OD(外包)转正名额被炒到 10-30 万一个,内推费更是高达 2 万/人,HR 和中介坐地分成,赚得盆满钵满。笔试环节直接产业化,专业替考团队上线,技术岗的代码题答案提前泄露,考生都不用自己动脑子。更离谱的是,入职后还有“双向吸血”套路:新员工得按月给“推荐人”返现,而管理层则通过审批权抽成,上下通吃。这哪里是招聘,简直是“买票上车”的黑色产业链。

知情人士透露,这条链子在成都存储部门尤为猖獗。有人戏称:“华为的 offer 不是靠实力拿的,是靠钱砸出来的。”金额规模据说超亿元,难怪这次高层震怒,直接祭出大招。

清理手段有多狠?

华为这次的反腐可不是喊口号,而是真刀真枪干到底。涉事员工被集中隔离到独立办公区,手机电脑全没收,一个个接受问询,气氛堪比电视剧里的审讯现场。某研发部门一天之内裁撤超 150 人,其中 50 多个还是正式员工,所有权限 24 小时内注销,效率高得让人咋舌。更绝的是,离职补偿?不存在的。股票、期权、奖金全冻结,离职证明上还直接标注“诚信问题”,这辈子别想再进华为。

相比之下,字节之前的清理行动简直是“小儿科”。华为这波连坐清退+零容忍,直接把“高压线”拉到满格。内部流出的《廉洁公告》写得明白:“凡触碰高压线者,无论职级,终身不录用。”这话放出来,谁还敢乱来?

风暴背后的信号

这次风暴来得突然,但细想也不意外。华为这几年在内外压力下,业务扩张快,人员流动大,管理漏洞难免被钻空子。尤其是成都基地,作为存储业务的重镇,招聘量大,腐败的土壤自然肥沃。但高层显然不想让这颗“毒瘤”继续长下去,直接下狠手割掉,震慑意味拉满。

有网友调侃:“华为这是要用反腐给自己立个新标杆啊。”不过也有人担心,这种大刀阔斧的清理会不会伤及无辜,毕竟连坐制下,难免有“躺枪”的。无论如何,这场风暴已经让菊厂的员工绷紧了神经,HR 和中介估计也得消停一阵了。

华为这波反腐,狠辣程度刷新了圈内认知。从明码标价的腐败链到隔离审查的雷霆手段,菊厂用行动证明:高压线不是摆设,触碰的下场就是“死路一条”。至于后续会不会有更多猛料爆出,咱们吃瓜群众就拭目以待吧。


回归正题,我们来一道力扣的题目

3434. 子数组操作后的最大频率

题目地址

https://leetcode.cn/problems/maximum-frequency-after-subarray-operation/

题目描述

给定一个整数数组 nums 和一个整数 k,你可以对数组执行以下操作任意次:

  • 选择一个子数组,将其中所有元素增加或减少 1。

目标是使数组中某个数的频率(出现次数)最大化。返回经过若干次操作后,数组中可能达到的最大频率。

示例 1:

1
2
3
输入: nums = [1,2,4], k = 5
输出: 3
解释: 通过操作,可以将数组变为 [2,2,2],最大频率为 3。

示例 2:

1
2
3
输入: nums = [1,4,8,13], k = 5
输出: 2
解释: 可以将 [1,4] 变为 [3,3],最大频率为 2。

约束:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5
  • 0 <= k <= 10^9

注意:您的代码中假设 nums[i] 的范围是 [1, 50],但题目实际范围是 [1, 10^5]。以下题解将基于题目原始约束调整。

思路

这道题操作只能进行一次,这个需要特别注意(题目其实也高亮显示了)。

这道题的目标是最大化某个数的频率。我们可以换个角度,将问题转化为:通过操作将子数组中的其他值变为某个目标值 k,从而增加 k 的频率。

分析

我们可以枚举所有子数组,然后再枚举增加或者减少的 x,观察增加或者减少后 k 有多少个。

这有两个问题:

  1. 首先枚举所有子数组就需要平方复杂度,题目中数组长度是 10^5,这就已经超时了。
  2. 再枚举一次子数组,又需要线性复杂度。

那么如何优化呢?

注意到这道题值域只有 50,是否是一个有效提示呢?

是的,我们可以反过来想,我们不是想通过增加 x 或者减少 x 来增加 k 的频率吗?那么最终增加的频率一定是非 k 的数转化来的,并且这些数是同一个数 y。假设这样的数有 10 个,k 对应频率就增加 10。最后我们减去通过操作使得原来是 k 的变为非 k 的个数即可,这不难,只需要统计子数组 k 的个数即可。

既然变为 k 的只能是某一个数字,我们不妨枚举这个 y。由于这个 y 只有 50,而不是 10^5,所以枚举范围可以缩小。

确定好了 y,接下来我们需要确定的是哪个子数组使得结果最大,如果这个也确定了,答案就出来了。

那么接下来我们就来考虑如何确定子数组。

  • 如果被操作的子数组中有 y,相当于 + 1,子数组中有 k 相当于 -1,这两者都不是 +0。这里的 -1,-0,+1 本质上是对答案的贡献。
  • 这样问题转化为给定 y 的情况下,给你一个值为-1,0,1 的子数组,求子数组最大值,这是一个典型的“子数组最大值问题”
  • “子数组最大值问题” 可以用动态规划来解决,也可以维护前缀和,用前缀和减去最小前缀和就是以当前元素为结尾的最大子数组和(我们就用这种方法)

最后总结一下:

  1. 枚举变为 k 的数 y
  2. 根据 y 将 nums 处理为 -1、0、1 数组
  3. 求子数组最大值。我们可以用前缀和减去最小前缀和

具体步骤

  1. Counter 统计 nums 中每个值的初始频率。
  2. 枚举目标值 v
  3. 对于每个 v
    • 遍历 nums,构建新数组:num == k 时值为 -1num == v 时值为 1,否则为 0
    • 用前缀和 pre 和最小前缀和 minPre 计算最大子数组和 maxSubarray
  4. 最终答案为 k 的初始频率加上能增加的最大值 maxSubarray

代码

Python 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
def maxFrequency(self, nums, k):
# 枚举将子数组中的 x 都变为 k,如果子数组中有 x,相当于 + 1,子数组中有 k 相当于 -1
# 这样问题转化为给定 x 的情况下,给你一个值为-1,0,1 的子数组,求子数组最大值,这是一个典型的“子数组最大值问题”,可以用动态规划来解决,也可以维护前缀和,用前缀和减去最小前缀和就是以当前元素为结尾的最大子数组和(我们就用这种方法)
counter = Counter(nums)
kCnt = counter[k]
ans = 0 # 增加的 k 的个数
for v in range(1, 51):
if v == k: continue # 没必要算
minPre = maxSubarray = pre = 0
for num in nums:
if num == v:
pre += 1
elif num == k:
pre -= 1
maxSubarray = max(maxSubarray, pre - minPre)
minPre = min(minPre, pre)

ans = max(ans, maxSubarray)

return kCnt + ans

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.HashMap;
import java.util.Map;

class Solution {
public int maxFrequency(int[] nums, int k) {
Map<Integer, Integer> counter = new HashMap<>();
for (int num : nums) {
counter.put(num, counter.getOrDefault(num, 0) + 1);
}
int kCnt = counter.getOrDefault(k, 0);
int ans = 0; // 增加的 k 的个数
for (int v = 1; v <= 50; v++) {
if (v == k) continue; // 没必要算
int minPre = 0, maxSubarray = 0, pre = 0;
for (int num : nums) {
if (num == v) {
pre += 1;
} else if (num == k) {
pre -= 1;
}
maxSubarray = Math.max(maxSubarray, pre - minPre);
minPre = Math.min(minPre, pre);
}
ans = Math.max(ans, maxSubarray);
}
return kCnt + ans;
}
}

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <vector>
#include <unordered_map>
#include <algorithm>

using namespace std;

class Solution {
public:
int maxFrequency(vector<int>& nums, int k) {
unordered_map<int, int> counter;
for (int num : nums) {
counter[num]++;
}
int kCnt = counter[k];
int ans = 0; // 增加的 k 的个数
for (int v = 1; v <= 50; v++) {
if (v == k) continue; // 没必要算
int minPre = 0, maxSubarray = 0, pre = 0;
for (int num : nums) {
if (num == v) {
pre += 1;
} else if (num == k) {
pre -= 1;
}
maxSubarray = max(maxSubarray, pre - minPre);
minPre = min(minPre, pre);
}
ans = max(ans, maxSubarray);
}
return kCnt + ans;
}
};

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var maxFrequency = function (nums, k) {
let counter = {};
for (let num of nums) {
counter[num] = (counter[num] || 0) + 1;
}
let kCnt = counter[k] || 0;
let ans = 0; // 增加的 k 的个数
for (let v = 1; v <= 50; v++) {
if (v === k) continue; // 没必要算
let minPre = 0,
maxSubarray = 0,
pre = 0;
for (let num of nums) {
if (num === v) {
pre += 1;
} else if (num === k) {
pre -= 1;
}
maxSubarray = Math.max(maxSubarray, pre - minPre);
minPre = Math.min(minPre, pre);
}
ans = Math.max(ans, maxSubarray);
}
return kCnt + ans;
};

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import "fmt"

func maxFrequency(nums []int, k int) int {
counter := make(map[int]int)
for _, num := range nums {
counter[num]++
}
kCnt := counter[k]
ans := 0 // 增加的 k 的个数
for v := 1; v <= 50; v++ {
if v == k {
continue // 没必要算
}
minPre, maxSubarray, pre := 0, 0, 0
for _, num := range nums {
if num == v {
pre += 1
} else if num == k {
pre -= 1
}
if pre-minPre > maxSubarray {
maxSubarray = pre - minPre
}
if pre < minPre {
minPre = pre
}
}
if maxSubarray > ans {
ans = maxSubarray
}
}
return kCnt + ans
}

复杂度分析

  • 时间复杂度O(n * 50)
  • 空间复杂度O(n)

力扣专属折扣

力扣免费题目已经有了很多经典的了,也覆盖了所有的题型,只是很多公司的真题都是锁定的。个人觉得如果你准备找工作的时候,可以买一个会员。另外会员很多 leetbook 也可以看,结合学习计划,效率还是蛮高的。

现在力扣在每日一题基础上还搞了一个 plus 会员挑战,每天刷题可以获得积分,积分可以兑换力扣周边。

如果你要买力扣会员的话,这里有我的专属力扣折扣:https://leetcode.cn/premium/?promoChannel=lucifer (年度会员多送两个月会员,季度会员多送两周会员)


 评论


博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

本站使用 Material X 作为主题 。
载入天数...载入时分秒...