今天给一个老员工降薪20% 他本来月薪15000,降完剩12000。我本以为他会很生气,甚至找我吵一架,结果他沉默了几分钟!!
这老板还挺会给自己找心理安慰。
37岁的老员工,干了五年,工资从一万五砍到一万二。家里房贷车贷加起来每个月快一万,他没拍桌子,也没骂人,就憋了半天说句“行”。这哪是没脾气啊,这明显是人到中年,连发火都得先算账。
最扎心的是老板那句“业绩中不溜,公司利润下滑,就先从他开刀”。听着就像挑软柿子捏。后来又补一千,好像自己已经很有人情味了。
他看着工资条想说没说,估计心里已经把简历打开了。只是成年人离职也不能像电视剧那样潇洒,得先看看下个月贷款谁来还。
abcdefg 右旋 2 位,结果应该是 fgabcde。
这个题第一眼别急着上 substring。面试里当然能过,但我一般不太喜欢一上来就切字符串,尤其是题目明说要你“原地处理”或者空间复杂度尽量低的时候,substring 这条路基本就不稳了。
右旋字符串,说穿了就是把尾巴那一截搬到前面。
比如:
s = abcdefg
k = 2
尾巴:fg
前面:abcde
结果:fgabcde
最容易写的办法是这样:
String ans = s.substring(s.length() - k) + s.substring(0, s.length() - k);
能用,但这段代码我只会拿来做验证,不会当最终写法。因为它重新创建了字符串,思路也太依赖库函数了,算法题里看着有点偷懒。
更稳的写法是“三次反转”。
原字符串:
abcdefg
先整体反转:
gfedcba
再把前 k 个字符反转:
fgedcba
最后把后面剩下的字符反转:
fgabcde
代码可以这样写:
publicclassRotateText{
publicstatic String rightRotate(String text, int step){
if (text == null || text.length() == 0) {
return text;
}
char[] chars = text.toCharArray();
int n = chars.length;
step = step % n;
if (step == 0) {
return text;
}
reverse(chars, 0, n - 1);
reverse(chars, 0, step - 1);
reverse(chars, step, n - 1);
returnnew String(chars);
}
privatestaticvoidreverse(char[] chars, int left, int right){
while (left < right) {
char tmp = chars[left];
chars[left] = chars[right];
chars[right] = tmp;
left++;
right--;
}
}
publicstaticvoidmain(String[] args){
System.out.println(rightRotate("abcdefg", 2)); // fgabcde
System.out.println(rightRotate("hello", 7)); // lohel
System.out.println(rightRotate("java", 4)); // java
}
}
这里有个地方别手滑。
step = step % n 这行不能省。因为右旋 7 位和右旋 2 位,在长度为 5 的字符串里效果是一样的。没取模的话,后面 reverse(chars, 0, step - 1) 直接就越界了。
我以前看这种题,最烦那种一上来写一堆判断的代码,其实没必要。关键就三个判断:
字符串为空,直接返回;
旋转位数取模;
取模后等于 0,也直接返回。
剩下的交给反转函数。
这个题考的不是 Java API,而是你能不能把“搬动一段字符”转换成“反转几次”。数组、字符串、链表里很多题都是这个味道,看着是在移动,真动起来成本高,那就换个角度,用局部反转把顺序调出来。