程序员老鬼

我和对象都是外包,现在我转正了,要不要分手

“都是外包”的时候没分,“你转正了”就想分,这事一听就不太像感情问题,典型的,上岸第一剑,先斩意中人,身份一变,心态先飘了。

Image

我对这种事的判断一向很直接:该不该分,不看编制,不看工牌,先看这段关系里还有没有基本的尊重。你转正,是你努力换来的结果,不是拿来给另一半打分的尺子。今天你嫌他外包,明天别人嫌你平台一般,这套逻辑转一圈,最后谁都站不稳。

真要想清楚,别盯着“外包”两个字,盯三件事:对方靠不靠谱,遇事扛不扛,日子能不能一起往前过。工作身份会变,行情也会变,人品和相处方式没那么容易演。拿转正当分手理由,说白了,薄的不是劳动合同,是感情。

算法题:超过 5 名学生的课

一眼看这题,很多人会顺手上 Set,结果写着写着就发现不对:题目要的不是“有哪些学生”,而是“哪门课的人数超过 5”。统计对象错了,后面全白忙。

这题叫超过 5 名学生的课,本质不复杂,就是一遍计数。难点不在算法,在于别把方向写歪。你盯着 student 字段看半天没用,真正该盯的是 className。

假设报名记录长这样:

classRecord{
    String student;
    String className;

    Record(String student, String className) {
this.student = student;
this.className = className;
    }
}

我平时写这种题,第一反应就是 HashMap<String, Integer>。先把每门课出现次数压出来,再扫一遍把大于 5 的课捞出来,够了。

import java.util.*;

publicclassSolution{
public List<String> findClasses(List<Record> records){
        Map<String, Integer> counter = new HashMap<>();

for (Record r : records) {
            counter.put(r.className, counter.getOrDefault(r.className, 0) + 1);
        }

        List<String> ans = new ArrayList<>();
for (Map.Entry<String, Integer> entry : counter.entrySet()) {
if (entry.getValue() > 5) {
                ans.add(entry.getKey());
            }
        }
return ans;
    }
}

这段代码时间复杂度是 O(n),空间复杂度也是 O(n)。面试里基本够用,别一上来就想什么花活。数据一共就过两遍,已经很实在了。

不过这题有个小坑,我见过有人没注意:同一个学生会不会重复选同一门课?如果题目没说不会,那你直接计数就可能虚高。这个时候就得先去重,不然 Tom 给 Math 重复插两次,人数就被你算多了。

可以这么补一层:

public List<String> findClassesDedup(List<Record> records){
    Map<String, Set<String>> map = new HashMap<>();

for (Record r : records) {
        map.computeIfAbsent(r.className, k -> new HashSet<>()).add(r.student);
    }

    List<String> ans = new ArrayList<>();
for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
if (entry.getValue().size() > 5) {
            ans.add(entry.getKey());
        }
    }
return ans;
}

你看,题还是那道题,代码差不了几行,判断味道就完全不一样了。很多题不是不会写,是没先把脏数据、重复数据这种边角料想清楚。

如果这是 SQL 题,思路其实也是一回事:group by class,再 having count(*) > 5。Java 版本不过是把数据库那套分组统计,自己在内存里手搓一遍。

这种题不值得绕。抓住“按课分组”这一个点,后面就顺了。真到面试现场,先把统计对象说对,比你背一堆复杂度术语有用。