程序员老鬼

奇怪,为什么今年投简历,没有任何回复?行情已经差成这样了吗

投出去100多份简历,全部都是已读不回,连个“暂不合适”都没有。

这事今年真不少,不一定是你不行,很多时候是岗位本身就不真招。 

有些岗挂着是为了刷流水、试探行情、顺手收一波便宜简历;有些公司HC临时冻结,JD还躺在那儿;还有一类更现实,岗位要的不是“能干活”,是“来了就顶住,还得便宜”。 

Image

所以别一上来就怀疑自己。

先查三件事:简历是不是还在写岗位职责,项目是不是没写结果,投递是不是只盯着公开招聘。

现在这行情,海投本身就越来越不值钱,内推、定向沟通、项目细节打磨,反而更管用。 

今年确实难,但也没难到投了就没机会。多数人卡住,不是能力断崖下滑,是还在用前两年的投法。

算法题:体育馆的人流量

闸机接口一到整点就飙高,监控上 QPS 没翻倍,数据库连接数却打满。最离谱的是,人流量统计接口偶发超时,日志里全是同一个 gymId。

我第一眼不看业务代码,先看数据量。查了下当天进出记录,某个体育馆一天 8 万条打卡记录。问题不在“有没有数据”,而在“怎么统计”。

题目其实不复杂:给一批进出记录,求某段时间内体育馆的最大同时在馆人数。

很多人上来就是两层循环,按时间片一段段扫。数据一大,直接卡死。

我一般会把这种问题当成“扫描线”问题。别管是人流、会议室、CPU 占用,本质一样:

  • 进入 +1
  • 离开 -1
  • 时间排序
  • 一路累加,取最大值

先定义记录结构:

classRecord{
long enterTime;
long leaveTime;

publicRecord(long enterTime, long leaveTime){
this.enterTime = enterTime;
this.leaveTime = leaveTime;
    }
}

别急着算人数,先把所有时间点打平。

classPoint{
long time;
int delta; // +1 or -1

    Point(long time, int delta) {
this.time = time;
this.delta = delta;
    }
}

核心逻辑很短:

publicintmaxPeople(List<Record> records){
    List<Point> points = new ArrayList<>();

for (Record r : records) {
        points.add(new Point(r.enterTime, 1));
        points.add(new Point(r.leaveTime, -1));
    }

// 时间相同,离开优先,避免误算
    points.sort((a, b) -> {
if (a.time == b.time) {
return a.delta - b.delta;
        }
return Long.compare(a.time, b.time);
    });

int cur = 0;
int max = 0;

for (Point p : points) {
        cur += p.delta;
if (cur > max) {
            max = cur;
        }
    }

return max;
}

这里有个细节,我现场排这种问题时一定会盯:

时间相同怎么办?

比如 10:00 有人离开,同时有人进入。如果你排序时进入排前面,就会瞬间多算一个人。

所以我把 -1 排在前面。时间相同,先减后加。

这种边界如果不想清楚,线上统计会多一两个人,看起来不大,但老板盯日报的时候你解释不清。

再说一个坑。

有同学会问:如果我要查某个时间区间内的最大人数呢?

比如 18:00–20:00 的高峰。

很多人会直接把所有记录丢进去算。其实不对。

你应该先过滤掉完全不相交的区间:

if (r.leaveTime <= start || r.enterTime >= end) {
continue;
}

然后把时间裁剪到查询区间内:

long realEnter = Math.max(r.enterTime, start);
long realLeave = Math.min(r.leaveTime, end);

否则会把全天峰值算进来。

再往下走一步。

如果数据是实时流式进来的怎么办?闸机不停上报,不能每次全量排序。

这时候我会换个思路:

用 TreeMap<Long, Integer> 做一个时间轴增量统计。

privatefinal TreeMap<Long, Integer> timeline = new TreeMap<>();

publicvoidaddRecord(long enter, long leave){
    timeline.merge(enter, 1, Integer::sum);
    timeline.merge(leave, -1, Integer::sum);
}

当需要统计时再顺序累加:

publicintcalculate(){
int cur = 0;
int max = 0;

for (Integer delta : timeline.values()) {
        cur += delta;
        max = Math.max(max, cur);
    }

return max;
}

时间复杂度从 O(n²) 变成 O(n log n)。数据量上来之后,差距不是一点点。

这种题本身不难,难的是现场感。

我见过线上版本是这样写的:

for (long t = start; t <= end; t++) {
int count = 0;
for (Record r : records) {
if (r.enterTime <= t && r.leaveTime > t) {
            count++;
        }
    }
    max = Math.max(max, count);
}

时间粒度按秒扫。一天 86400 秒,8 万条记录。

CPU 直接飙到 90%。

问题不是算法多复杂,是思路错了。

人流统计这种题,本质就是“区间重叠最大值”。

想清楚增减关系,比堆 if 判断重要。

写算法别急着敲代码。

先问自己一句:

这个问题能不能变成“排序 + 一次遍历”?

十有八九能。

体育馆是人流,系统里是线程,数据库里是连接。

换个壳,本质一样。