汇丰面试通过,给了 offer。。
刚刷到个贴子,说网友在外包干得挺舒服,不加班,节奏稳,结果汇丰突然发来 offer,要他一周内入职,整个人开始纠结。
我看完只想说:这还纠结啥,肯定去汇丰啊!外包的天花板太低了,你今天觉得舒服,是因为还没被淘汰。
汇丰再怎么催,也代表人家认可你,能给你更高的平台、更广的眼界。机会来了还犹豫,等它走了才后悔,那才叫不负责任。
“不想辜负现在的项目”,这想法挺善良,但职场从来不是情感账。你走了项目照样转,你留下待遇不会涨。职场最该忠诚的是自己,而不是某个暂时的岗位。
说到底,外包是温水,汇丰是大海。舒适是暂时的,成长才是长期的。能跳,就别怕浪。【备注:文末可领最新资料】
算法题:寻找最近的回文数
昨晚十一点多在公司楼下吹风,手机叮的一下,小李问我:“哥,最近的回文数怎么写?我写的老有边界问题。”我当场盘了一遍思路,顺手把代码也敲了,你们就跟着这个来,别走弯路哈。
目标:给一个非负整数 n(通常当成字符串处理),找与它“数值距离”最近的不同回文数;如果距离一样,取更小的那个。 难点都在边界:像 9、10、1000、999… 这种拐点,以及中间位进位/借位导致的连锁反应。
怎么稳?我一般构造一小撮“候选回文”,最后挑最接近的:
镜像原数:把左半边镜到右边,得到 same。注意它可能等于原数,需要剔除。前缀±1 再镜像:把“前缀”(含中位)加一、减一,再各镜一次,解决 129→131、199→202、1000→099? 这类进位借位。 两大保底: 10^k + 1(形如 100…001)和10^k - 1(形如 99…9),专治 999、1000 这种边界。
候选不多,最多五六个,逐个比差值,距离小者胜;平手取更小的值。为防溢出,用 long 比较,输入当字符串。
关键细节
前缀定义:长度 len,取前(len+1)/2位(奇数含中位,偶数不含中位)。镜像方法:把前缀拷到右侧反向位置,奇偶统一处理。 去重:候选可能重复,用 Set。排除自身:如果候选等于原数,跳过。 数字太大/太小:前缀加一可能长度变长(如 999→1000),减一可能出现前导零,这都交给“两大保底”兜底。
Java 实现(直接可用)
import java.util.*;
publicclassNearestPalindrome{
public String nearestPalindromic(String n){
int len = n.length();
long original = Long.parseLong(n);
Set<Long> cand = new HashSet<>();
// 两个保底
cand.add((long)Math.pow(10, len) + 1); // 1000..0001
cand.add((long)Math.pow(10, len - 1) - 1); // 99..99 (len-1位全9)
// 基于前缀的三个:prefix-1, prefix, prefix+1
long prefix = Long.parseLong(n.substring(0, (len + 1) / 2));
for (long p : newlong[]{prefix - 1, prefix, prefix + 1}) {
if (p < 0) continue;
String pal = buildPal(p, len);
try {
cand.add(Long.parseLong(pal));
} catch (NumberFormatException ignore) {} // 极端大数忽略
}
// 选最近(排除自身)
long ans = -1;
for (long x : cand) {
if (x == original) continue;
if (ans == -1) ans = x;
long diffA = Math.abs(x - original), diffB = Math.abs(ans - original);
if (diffA < diffB || (diffA == diffB && x < ans)) ans = x;
}
return String.valueOf(ans);
}
// 用前缀构造长度为 len 的回文
private String buildPal(long prefix, int len){
String s = String.valueOf(prefix);
StringBuilder left = new StringBuilder(s);
// 若前缀位数因进位变长,需要只取前半所需长度
if (left.length() > (len + 1) / 2) {
left.setLength((len + 1) / 2);
s = left.toString();
} elseif (left.length() < (len + 1) / 2) {
// 借位导致位数变短,前面补零
while (left.length() < (len + 1) / 2) left.insert(0, '0');
s = left.toString();
}
StringBuilder sb = new StringBuilder();
sb.append(s);
// 偶数:镜全部;奇数:跳过中位再镜
int start = (len % 2 == 0) ? s.length() - 1 : s.length() - 2;
for (int i = start; i >= 0; i--) sb.append(s.charAt(i));
return sb.toString();
}
// 小测
publicstaticvoidmain(String[] args){
NearestPalindrome np = new NearestPalindrome();
System.out.println(np.nearestPalindromic("1")); // 0
System.out.println(np.nearestPalindromic("9")); // 8
System.out.println(np.nearestPalindromic("10")); // 9
System.out.println(np.nearestPalindromic("1283")); // 1331
System.out.println(np.nearestPalindromic("999")); // 1001
System.out.println(np.nearestPalindromic("1000")); // 999
System.out.println(np.nearestPalindromic("12321")); // 12221
}
}
为啥这套稳定
因为“候选法”把所有会出事的场景都覆盖了:
镜像原数保证“就地修复”; 前缀±1解决中位进位/借位连锁; 10^k±1 把位数变化的边界牢牢兜住。 最后统一用差值+字典序规则挑选,就很稳。行了我先去泡杯茶,哪个测试还卡住,丢给我看下具体样例就行。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html