程序员老鬼

hr发帖,说自己拼死拼活帮公司省下150多万,结果一转头人就被裁了。。

刚刷到一个HR网友发帖,说自己拼死拼活帮公司省下150多万,结果一转头人就被裁了,吐槽“狡兔死走狗烹”。

Image

我觉得这事吧,说到底还是职场的“价值逻辑”:你创造的价值一旦无法持续交换,哪怕省了几百万,也可能瞬间失效。网友有人说“太惨了”,但也有人觉得他“不懂收手”。我偏向后者。

从我的角度看,程序员也别太沉迷于“贡献论”,公司不是GitHub,没人关心你commit了多少。重要的是,你现在能不能继续“可用”。

不过话说回来,被这样对待确实窝火。但也提醒我们:任何时候都要给自己留条后路。打工不易,得有自保意识。【备注:文末可领最新资料】

算法题:购买量严格增加的客户

那天中午我正吃着泡面,组里小刘突然发我一条消息,说他在LeetCode上刷到一道题,说实话我第一口面都还没咽下去,他就给我念起来了:“一个商店,有很多客户,每个客户买东西的时间记录下来,然后要找出那些购买量是严格递增的客户,连续三次以上。”我一边吸溜一边回:“啊?你是说...比如某人第一天买1件,第二天买3件,第三天买5件,那就算了?”

他说对,就是这样,但是得是连续的记录里买的越来越多,不能间隔。说实话我第一反应是这个不难,扫一遍就完了。但后来细想,数据量一大,稍不注意就超时。Java写这类题吧,不像Python那么“流”,但一旦思路清楚,Java那种严谨劲儿还是挺舒服的。

我们就拿这几个字段说事:customer_id, order_date, quantity。基本结构一清楚,咱们就可以开搞了。

我那天是这么写的哈,就直接说关键代码,别指望我copy全套类结构,自己脑补一下:

Map<String, List<Order>> orderMap = new HashMap<>();

你猜这是干嘛的?就是先把所有客户的订单按客户ID聚合起来,然后每个客户的订单按时间排序。这个Order是我自定义的类,里面就三字段:时间、数量、还有原始顺序。Java里你要比较时间肯定得转成LocalDate,不然字符串对比太不靠谱。

聚合完之后,我们得干一件事——滑窗。我那天说的就是:“你就想象一下,把每个客户的订单当成一列数,然后你拿个尺子量着,三格三格往后滑,看这三格是不是严格递增。”

我大致是这么写的:

for (Map.Entry<String, List<Order>> entry : orderMap.entrySet()) {
    List<Order> orders = entry.getValue();
    orders.sort(Comparator.comparing(o -> o.date));  // 按日期排好序

int count = 0;
for (int i = 2; i < orders.size(); i++) {
int q1 = orders.get(i - 2).quantity;
int q2 = orders.get(i - 1).quantity;
int q3 = orders.get(i).quantity;

if (q1 < q2 && q2 < q3) {
            result.add(entry.getKey());
break;
        }
    }
}

你看我也没用什么高深技巧,就老老实实地for loop,一遍遍比,别想那些“奇技淫巧”了,面试官要的是你清晰的逻辑。

对了,刚刚那段代码里我还漏了个细节,我是用Set<String>来装结果的,因为有些客户可能在后面还有别的递增段,你加一次就得停,别重复加了。

那天小刘还问我说:“哥,那你为啥不直接SQL里搞定?”我说你这不是小看SQL嘛,要在SQL里写一个滑窗,行,但SQL处理逻辑性稍微复杂点就麻烦,而且要是题目让你用Java,那就别偷懒。况且你还得考虑null、重复记录啥的。

其实这种题我印象挺深的,不光是代码简单,而是它特别“贴地气”——现实生活里就有这种需求。你看你电商平台做CRM画像,就得知道哪些客户买得越来越多,潜力股嘛。

写完代码那会儿已经两点了,泡面也凉了,小刘还在那反复跑样例,我当时直接回他一句:“你要是数据多,就记得用BufferedReader,不然Scanner一套下来直接TLE。”

对了,刚才那段不是开玩笑,真有些题用Scanner读百万行数据,光读数据都能卡你三秒。你要真的写到线上去,记得优化IO。

-END-

我为大家打造了一份RPA教程,完全免费:https://www.songshuhezi.com/rpa.html

最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领取,也可以链接我领取,微信:hls404