刚进公司,工牌还没捂热,同事先把你的钱包安排明白了:欢迎新人可以,直接点名2888海鲜套餐,这味儿就不对了。
这哪是欢迎,分明是试探。试探你脸皮薄不薄,好不好拿捏,会不会为了“融入集体”硬着头皮掏钱。
有网友说,这种局谁请谁冤,第一顿你认了,后面奶茶、聚餐、过节红包都能顺着往下接。还有人说得更狠:你请的不是客,是入场费。话糙,真不假。
我是真烦这种职场老毛病。公司要欢迎新人,公司出钱;同事想热闹,AA;一群老员工盯着新人开刀,HR看见都该眼皮跳一下。刚入职先学业务,别先学当冤种。2888的海鲜没吃到嘴里,职场潜台词倒是先塞满了。类似的糟心事怎么躲?提前看看面试求职板块的经验,或许能帮你少走弯路。
面试题:自除数
这道题你或许在面试中见过,思路不复杂,却非常考验基本功。
一看到“自除数”这题,很多人第一反应是先转字符串,一位一位拆。能做,但我第一眼就不太想这么写。算法题里凡是“按十进制位处理”的,能直接 % 10 和 / 10 解决的,尽量别绕到字符串,写出来更稳,跑起来也更干净。
这题本身不复杂:一个数如果能被它每一位上的数字整除,它就是自除数。比如 128,得同时满足 128 % 1 == 0、128 % 2 == 0、128 % 8 == 0。但这里有个很容易漏的坑:只要某一位是 0,直接判死刑。因为除数不能是 0,这种数不可能是自除数。
这类题我一般不先想“怎么收集答案”,而是先把“单个数字怎么判断”扣清楚。单个数字判断准了,外面套一层区间遍历就行,没什么花活。
先看核心判断逻辑:
private boolean isSelfDividing(int num) {
int x = num;
while (x > 0) {
int digit = x % 10;
if (digit == 0 || num % digit != 0) {
return false;
}
x /= 10;
}
return true;
}
这段代码就干了两件事:
第一,拿到当前最低位数字。第二,判断这个数字能不能整除原数。
注意这里我一直拿 num 去做整除判断,x 只是用来不断拆位。这个地方不少人写着写着会把 x % digit 写进去,结果逻辑就偏了。因为题目要求的是“原数能不能被每一位整除”,不是“拆到哪一步的临时值能不能整除”。
外层遍历就更直接了:
public List<Integer> selfDividingNumbers(int left, int right) {
List<Integer> ans = new ArrayList<>();
for (int i = left; i <= right; i++) {
if (isSelfDividing(i)) {
ans.add(i);
}
}
return ans;
}
完整写法放一起就是这样:
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<Integer> selfDividingNumbers(int left, int right) {
List<Integer> ans = new ArrayList<>();
for (int i = left; i <= right; i++) {
if (isSelfDividing(i)) {
ans.add(i);
}
}
return ans;
}
private boolean isSelfDividing(int num) {
int x = num;
while (x > 0) {
int digit = x % 10;
if (digit == 0 || num % digit != 0) {
return false;
}
x /= 10;
}
return true;
}
}
这题时间复杂度其实也挺直白。区间里每个数都检查一次,而每次检查最多处理它的位数,所以复杂度就是 O(n * k),n 是区间长度,k 是数字位数。因为整数位数很有限,实际跑起来很轻。
这种题不考什么高深算法,考的是基本功:取位、判边界、别写歪。尤其是 0 这一位,很多提交错就错在这。题不难,但很适合看一个人的代码是不是利索。越是这种小题,越容易把细节写毛躁。