晚上7点多,部门主管突然微信跟我说,有一笔1500元的团队激励奖,要跟工资一起发到我卡上,让我收到后再转给人事~
晚上7点多,主管突然发微信,说有一笔1500元团队激励奖已经跟工资一起打到我卡里,让我到账后再转给人事文员分给其他同事。
钱既然能发到我卡上,说明财务、人事系统里已经能操作到个人账户。那为什么不直接一人一笔,非要绕我这一手?这种“先到你卡,再转别人”的流程,最麻烦的不是转账,是责任也跟着落到你头上。
要我说真碰到这种事,别急着回“收到”。先走两步:第一,要求主管在公司正式群里说,带上人事和财务;第二,直接打公司公开电话核实。
凡是奖金、补贴、报销,流程越反常,越要多问一句。很多坑,都是不好意思开口那一下掉进去的。
算法题:分数加减运算
字符串一长,很多人这题就开始上模板了:先通分,再相加,再约分。结果一写就乱,尤其是负号、整数部分、-1/2+1/2 这种边界,一不留神就翻车。
“分数加减运算”这题,其实不难,麻烦点全在细节。题目通常会给你一个表达式,比如:
-1/2+1/2+1/3
要求输出最简结果。能约分就约分;如果最后是整数,就直接输出整数;如果是 0,也别给我整成 0/1 之外的怪东西。
这类题我一般不急着拆一堆对象,先抓主线:整个表达式本质上就是一串分数累加。那就维护两个量:
当前分子 num当前分母 den
每读到一个新的分数 a/b,就做一次合并:
num = num * b + a * den;
den = den * b;
然后立刻约分,别等到最后。因为中间值会越来越大,虽然这题数据范围通常不大,但早点收缩总没坏处。
关键代码先看一眼:
privatestaticlonggcd(long a, long b){
a = Math.abs(a);
b = Math.abs(b);
while (b != 0) {
long t = a % b;
a = b;
b = t;
}
return a;
}
约分就靠它。每次算完新分子分母,顺手做一下:
long g = gcd(num, den);
num /= g;
den /= g;
还有个细节,分母最好始终保持正数,不然后面输出很别扭:
if (den < 0) {
num = -num;
den = -den;
}
完整写法我会更偏这种,直接扫字符串,不额外切太多片段:
classSolution{
public String fractionAddition(String expression){
long num = 0;
long den = 1;
int i = 0, n = expression.length();
while (i < n) {
int sign = 1;
if (expression.charAt(i) == '+' || expression.charAt(i) == '-') {
sign = expression.charAt(i) == '-' ? -1 : 1;
i++;
}
long a = 0;
while (i < n && Character.isDigit(expression.charAt(i))) {
a = a * 10 + (expression.charAt(i) - '0');
i++;
}
i++; // 跳过 '/'
long b = 0;
while (i < n && Character.isDigit(expression.charAt(i))) {
b = b * 10 + (expression.charAt(i) - '0');
i++;
}
a *= sign;
num = num * b + a * den;
den = den * b;
long g = gcd(num, den);
num /= g;
den /= g;
if (den < 0) {
num = -num;
den = -den;
}
}
return num + "/" + den;
}
privatelonggcd(long a, long b){
a = Math.abs(a);
b = Math.abs(b);
while (b != 0) {
long t = a % b;
a = b;
b = t;
}
return a;
}
}
这段代码的路子很直。
先读符号,再读分子,再跳过 /,再读分母。每拿到一个分数,就跟当前结果合并。这样不用先把所有分数存起来,边读边算就行。
拿 -1/2+1/2+1/3 走一遍:
第一步:0/1 + (-1/2) = -1/2第二步:-1/2 + 1/2 = 0/1第三步:0/1 + 1/3 = 1/3
最后输出 1/3。
这题真正容易错的地方就三个。
一个是第一个分数可能带负号,所以开头就得先判断 + 或 -。 一个是每次都要约分,不然中间分子分母膨胀得很快。 还有一个是0 的处理,约分后 0/x 最终都会收敛成 0/1,这一点用上面的写法天然就处理掉了。
算法复杂度也没什么花活,整体就是扫一遍字符串,时间复杂度 O(n),额外空间基本是 O(1)。
这种题放在算法里不算难题,但很适合看一个人的代码习惯。写得太急,就会在符号、约分、边界上丢分。看着只是分数相加,真到提交的时候,往往不是思路错,是手太快。