程序员老鬼

破防!十面字节仍被挂,新称号“挂面” ,一直面,一直挂…

刚看到个贴子,说有同学秋招连着冲了字节四个岗位、十次面试,结果还在原地踏步,网友们都给他整出个外号“挂面”,一直面一直挂,属实有点破防。

Image

我觉得人家能坚持十次已经是强心脏了。

从我的角度看,连续被挂不一定说明能力不行,更多时候是节奏、岗位需求、团队优先级这些因素乱七八糟地叠一起,就像排队买奶茶,前面的人突然全点大杯加料,你就只能干等着,并不代表你点单不行。

不过话说回来,这位同学的坚持确实值得夸。十次还敢继续冲,说实话已经比不少朋友强太多了。秋招这种东西,有时候拼的就是厚脸皮和续航力。

总的来说吧,别被一次次挂心态打崩,机会有时候拐个弯就来了。【备注:文末可领最新资料】

面试题:验证IP地址

我先直接上结论:验证 IP 地址这种题,本质就是字符串分类 + 规则校验,别被“网络”“协议”这些词吓到,其实就是拆字符串、看格式。

你想象一下,后端有个接口,前端传一个白名单 IP,上来就直接塞数据库里,结果有同事手一抖传了个 999.999.999.999,或者传个 "abcd",你再拿这些去做防火墙配置、限流规则,基本等于白忙活。

所以通常我们会写一个 validIPAddress(String queryIP),返回:

  • "IPv4"
  • "IPv6"
  • "Neither"

然后在业务里根据结果决定要不要接受这条配置。

不用背标准,只要记住常见的那版(跟面试/刷题常见版本对齐):

IPv4:

  • 形如:x.x.x.x
  • 一共 4 段,每段都要是十进制数字
  • 每段范围 0 ~ 255
  • 不能有前导零(除了单独一个 "0"),比如 01、001 都是不合法的
  • 不能有空段:1..1.1 这种拆出来有空串,直接判错

IPv6:

  • 形如:x:x:x:x:x:x:x:x
  • 一共 8 段,每段 1~4 个字符
  • 字符只能是十六进制:0-9、a-f、A-F
  • 可以有前导零,比如 0001 是 OK 的
  • 为了简单(也跟很多题目一致),不支持压缩写法:像 ::1、2001:db8::1 都当成非法

逻辑就变成一句话:先看是点多还是冒号多,猜它想当 IPv4 还是 IPv6,然后按相应规则“挑刺”,一旦有一条不符合就判死刑。

Java 实现:一眼能看懂的那种

直接给一个完整的类,你可以丢到 LeetCode 468 那题里跑:

publicclassIPAddressValidator{

public String validIPAddress(String queryIP){
if (queryIP == null || queryIP.isEmpty()) {
return"Neither";
        }
if (queryIP.indexOf('.') >= 0 && queryIP.indexOf(':') == -1) {
return isIPv4(queryIP) ? "IPv4" : "Neither";
        }
if (queryIP.indexOf(':') >= 0 && queryIP.indexOf('.') == -1) {
return isIPv6(queryIP) ? "IPv6" : "Neither";
        }
return"Neither";
    }

privatebooleanisIPv4(String ip){
// 注意:split 的参数是正则,“.” 要转义,而且要用 limit=-1 保留空段
        String[] parts = ip.split("\\.", -1);
if (parts.length != 4) {
returnfalse;
        }
for (String part : parts) {
// 不能为空
if (part.length() == 0) {
returnfalse;
            }
// 长度不能超过 3
if (part.length() > 3) {
returnfalse;
            }
// 不能有前导零,除非就是 "0"
if (part.length() > 1 && part.charAt(0) == '0') {
returnfalse;
            }
// 必须全是数字
int num = 0;
for (int i = 0; i < part.length(); i++) {
char c = part.charAt(i);
if (c < '0' || c > '9') {
returnfalse;
                }
                num = num * 10 + (c - '0');
            }
// 范围 0~255
if (num < 0 || num > 255) {
returnfalse;
            }
        }
returntrue;
    }

privatebooleanisIPv6(String ip){
        String[] parts = ip.split(":", -1);
if (parts.length != 8) {
returnfalse;
        }
for (String part : parts) {
// 每一段 1~4 个字符
int len = part.length();
if (len < 1 || len > 4) {
returnfalse;
            }
for (int i = 0; i < len; i++) {
char c = part.charAt(i);
boolean isDigit = c >= '0' && c <= '9';
boolean isLowerHex = c >= 'a' && c <= 'f';
boolean isUpperHex = c >= 'A' && c <= 'F';
if (!isDigit && !isLowerHex && !isUpperHex) {
returnfalse;
                }
            }
        }
returntrue;
    }

// 小 main,自己本地玩一玩
publicstaticvoidmain(String[] args){
        IPAddressValidator v = new IPAddressValidator();
        System.out.println(v.validIPAddress("172.16.254.1"));            // IPv4
        System.out.println(v.validIPAddress("2001:0db8:85a3:0:0:8A2E:0370:7334")); // IPv6
        System.out.println(v.validIPAddress("256.256.256.256"));         // Neither
        System.out.println(v.validIPAddress("1e1.4.5.6"));               // Neither
    }
}

这个题看着简单,其实面试里很多人会栽在细节里:

  • String.split 的坑:ip.split(".") 是错的,因为 . 在正则里代表“任意字符”。必须写成 "\\."。 还有就是默认 split 会丢掉末尾的空串,比如 "1.1.1." 用默认 split("\\.") 出来只有 3 段,你以为长度对了,其实不对。所以加上 -1 这个 limit,告诉它“空的也给我保留”。

  • 前导零:0 合法,00、01 都不行,这个很多人一开始没注意。

  • IPv6 压缩写法: 如果你是刷题,就按题目的简单版本来,直接 8 段死判。 真要做线上工具,再去支持 :: 这种压缩,那就是另一个难度了。

整体思路就是:不要试图用一个正则一口气把 IPv4、IPv6 全搞定,分两种情况慢慢检查,逻辑清楚、好调试,线上出了问题也方便打日志定位。你先把这版写熟,后面再想扩展别的花活也不迟。

-END-

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

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