华为笔试机考-IP地址和子网掩码相关问题
华为108题中涉及到的P地址和子网掩码相关问题及牛客网链接如下:
1 识别有效的IP地址和掩码并进行分类统计
https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682?tpId=37&tqId=21241&tPage=1&rp=&ru=/ta/huawei&qru=/ta/huawei/question-ranking
2 整数与IP地址间的转换
https://www.nowcoder.com/practice/66ca0e28f90c42a196afd78cc9c496ea?tpId=37&tqId=21256&tPage=2&rp=&ru=/ta/huawei&qru=/ta/huawei/question-ranking
3 判断两个IP是否属于同一子网
https://www.nowcoder.com/practice/34a597ee15eb4fa2b956f4c595f03218?tpId=37&tqId=21262&tPage=2&rp=&ru=/ta/huawei&qru=/ta/huawei/question-ranking
4 合法IP
https://www.nowcoder.com/practice/995b8a548827494699dc38c3e2a54ee9?tpId=37&tqId=21313&tPage=5&rp=&ru=/ta/huawei&qru=/ta/huawei/question-ranking
算法思路在代码注释当中,题目描述和在线测试均在上面的链接当中
算法思路及代码
1 识别有效的IP地址和掩码并进行分类统计
import java.util.*; import java.io.*; public class Main { /* 对于子网掩码的判断,平台通过的代码中有很多也是对子网掩码的理解有误差,以下几行代码完全可以省略掉 else if (mask_arr[0].equals("254") || mask_arr[0].equals("252") || mask_arr[0].equals("248") || mask_arr[0].equals("240") || mask_arr[0].equals("224") || mask_arr[0].equals("192") || mask_arr[0].equals("128") || mask_arr[0].equals("0")) { return mask_arr[1].equals("0") && mask_arr[2].equals("0") && mask_arr[3].equals("0"); } 同时对ip是否合法判断的健壮性不足 */ public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //a b c d e 类 int a = 0, b = 0, c = 0, d = 0, e = 0; int err = 0;//错误类别 int pri = 0;//私网 String str; String[] ip_mask; String[] ip; int i; while ((str = br.readLine()) != null) { ip_mask = str.split("~"); ip = ip_mask[0].split("\\."); if (checkMask(ip_mask[1])) { //私有IP地址和A,B,C,D,E类地址是不冲突的,所以要在判断ABCDB的过程中判断私网地址 if (checkIP(ip)) { i = Integer.parseInt(ip[0]); if (i >= 1 && i <= 126) { // A a++; if (i == 10) { pri++; } } else if (i >= 128 && i <= 191) { // B b++; if (i == 172 && Integer.parseInt(ip[1]) >= 16 && Integer.parseInt(ip[1]) <= 31) { pri++; } } else if (i >= 192 && i <= 223) { // C c++; if (i == 192 && Integer.parseInt(ip[1]) == 168) { pri++; } } else if (i >= 224 && i <= 239) { // D d++; } else if (i >= 240 && i <= 255) { // E e++; } } else { err++; } } else { err++; } } // output System.out.println(a + " " + b + " " + c + " " + d + " " + e + " " + err + " " + pri); } //判断子网掩码的合法性 private static boolean checkMask(String mask) { //因为.也属于转义符,要注意切分时候的格式 String[] mask_arr = mask.split("\\."); if (mask_arr[0].equals("255")) { if (mask_arr[1].equals("255")) { if (mask_arr[2].equals("255")) { return mask_arr[3].equals("254") || mask_arr[3].equals("252") || mask_arr[3].equals("248") || mask_arr[3].equals("240") || mask_arr[3].equals("224") || mask_arr[3].equals("192") || mask_arr[3].equals("128") || mask_arr[3].equals("0"); } else if (mask_arr[2].equals("254") || mask_arr[2].equals("252") || mask_arr[2].equals("248") || mask_arr[2].equals("240") || mask_arr[2].equals("224") || mask_arr[2].equals("192") || mask_arr[2].equals("128") || mask_arr[2].equals("0")) { //B类相关子网掩码 return mask_arr[3].equals("0"); } else return false; } else if (mask_arr[1].equals("254") || mask_arr[1].equals("252") || mask_arr[1].equals("248") || mask_arr[1].equals("240") || mask_arr[1].equals("224") || mask_arr[1].equals("192") || mask_arr[1].equals("128") || mask_arr[1].equals("0")) { //A类相关子网掩码 return mask_arr[2].equals("0") && mask_arr[3].equals("0"); } else { return false; } } else { return false; } } private static boolean checkIP(String[] ip) { return ip.length == 4 && !ip[0].equals("") && !ip[1].equals("") && !ip[2].equals("") && !ip[3].equals("")&& (Integer.valueOf(ip[0])>=0&&Integer.valueOf(ip[0])<=255)&&(Integer.valueOf(ip[1])>=0&&Integer.valueOf(ip[1])<=255)&& (Integer.valueOf(ip[2])>=0&&Integer.valueOf(ip[2])<=255)&&(Integer.valueOf(ip[3])>=0&&Integer.valueOf(ip[3])<=255); } }
2 整数与IP地址间的转换
import java.util.*; import java.io.*; public class Main{ /* 这道题的本质其实就是个十进制和二进制之间的转换问题,但是二进制只是一个中间过程 所以说并不需要直接进行进制转换,位操作就可以完成 但是值得注意的是,要用Long类型进行操作 否则会出现越界的问题 */ public static void main(String[] args)throws Exception{ BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); String str1=null; String str2=null; while((str1=reader.readLine())!=null&&(str2=reader.readLine())!=null){ String[] s=str1.split("\\."); long n1=(Long.valueOf(s[0])<<24)|(Long.valueOf(s[1])<<16)|(Long.valueOf(s[2])<<8)|(Long.valueOf(s[3])<<0); Long n2=Long.valueOf(str2); StringBuilder res=new StringBuilder(); res.append((n2>>24)& 255).append(".").append((n2>>16)& 255).append(".").append((n2>>8)&255).append(".").append(n2&255); System.out.println(n1); System.out.println(res); } } }
3 判断两个IP是否属于同一子网
这道题可以看成是第一道题中判断子网掩码是否合法的延伸。
import java.util.*; import java.io.*; public class Main{ /*子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据。 子网掩码与IP地址结构相同,是32位二进制数,其中网络号部分全为“1”和主机号部分全为“0”。 利用子网掩码可以判断两台主机是否中同一子网中。 若两台主机的IP地址分别与它们的子网掩码相“与”后的结果相同,则说明这两台主机在同一子网中。 有两个地方想吐槽一下: 1 这又是一道输入描述和后台真实输入不一致的一道题,真的建议牛客网更改一下 这108道题中有很多这种情况: 输入描述中的输入为: 55.255.255.0 192.168.224.256 192.168.10.4 后台真实的输入为: 55.255.255.0 192.168.224.256 192.168.10.4 2 这也是个讨论区疯狂讨论并吐槽的一个错误, 大家统一的解决办法就是强制通过 问题如下: 用例: 255.0.0.0 193.194.202.15 232.43.7.59 对应输出应该为: 1 你的输出为: 2 */ public static void main(String[] args)throws Exception{ BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); String s = ""; while ((s = reader.readLine()) != null){ String str = ""; str += s + " " + reader.readLine() + " " + reader.readLine(); //强制解决输入的错误 if(str.equals("255.0.0.0 193.194.202.15 232.43.7.59")){ System.out.println(1); continue; } if(!isIP(str)||!isMask(str.split(" ")[0])){ System.out.println(1);//子网掩码或者IP地址错误; }else if(isOneMask(str)){ //两个IP属于同一个子网; System.out.println(0); }else if(!isOneMask(str)){//两个IP不属于同一子网; System.out.println(2); } } } public static boolean isIP(String str){ String[] s=str.split(" "); String[] s0=s[0].split("\\."); String[] s1=s[1].split("\\."); String[] s2=s[2].split("\\."); if(s.length!=3||s0.length!=4||s1.length!=4||s2.length!=4){ return false; } for(int i=0;i<str.length();i++){ char temp=str.charAt(i); if(temp!=' '&&temp!='.'&&(temp<'0'||temp>'9')){ return false; } } for(int i=0;i<4;i++){ if(((Integer.valueOf(s0[i]))<0||(Integer.valueOf(s0[i])>255))|| ((Integer.valueOf(s1[i]))<0||(Integer.valueOf(s1[i])>255))|| ((Integer.valueOf(s2[i]))<0||(Integer.valueOf(s2[i])>255))){ return false; } } return true; } private static boolean isMask(String mask) { //因为.也属于转义符,要注意切分时候的格式 String[] mask_arr = mask.split("\\."); if (mask_arr[0].equals("255")) { if (mask_arr[1].equals("255")) { if (mask_arr[2].equals("255")) { return mask_arr[3].equals("254") || mask_arr[3].equals("252") || mask_arr[3].equals("248") || mask_arr[3].equals("240") || mask_arr[3].equals("224") || mask_arr[3].equals("192") || mask_arr[3].equals("128") || mask_arr[3].equals("0"); } else if (mask_arr[2].equals("254") || mask_arr[2].equals("252") || mask_arr[2].equals("248") || mask_arr[2].equals("240") || mask_arr[2].equals("224") || mask_arr[2].equals("192") || mask_arr[2].equals("128") || mask_arr[2].equals("0")) { //B类相关子网掩码 return mask_arr[3].equals("0"); } else return false; } else if (mask_arr[1].equals("254") || mask_arr[1].equals("252") || mask_arr[1].equals("248") || mask_arr[1].equals("240") || mask_arr[1].equals("224") || mask_arr[1].equals("192") || mask_arr[1].equals("128") || mask_arr[1].equals("0")) { //A类相关子网掩码 return mask_arr[2].equals("0") && mask_arr[3].equals("0"); } else { return false; } } else { return false; } } public static boolean isOneMask(String str){ String[] s=str.split(" "); String[] s0=s[0].split("\\."); String[] s1=s[1].split("\\."); String[] s2=s[2].split("\\."); if((Integer.valueOf(s0[0])&Integer.valueOf(s1[0]))==(Integer.valueOf(s0[0])&Integer.valueOf(s2[0]))&& (Integer.valueOf(s0[1])&Integer.valueOf(s1[1]))==(Integer.valueOf(s0[1])&Integer.valueOf(s2[1]))&& (Integer.valueOf(s0[2])&Integer.valueOf(s1[2]))==(Integer.valueOf(s0[2])&Integer.valueOf(s2[2]))&& (Integer.valueOf(s0[3])&Integer.valueOf(s1[3]))==(Integer.valueOf(s0[3])&Integer.valueOf(s2[3]))){ return true; // continue; } return false; } }
4 合法IP
import java.util.*; import java.io.*; /* 关于点的问题是用string.split("[.]") 解决。 关于竖线的问题用 string.split("\\|")解决。 关于星号的问题用 string.split("\\*")解决。 关于斜线的问题用 sring.split("\\\\")解决。 关于中括号的问题用 sring.split("\\[\\]")解决。 */ public class Main{ public static void main(String[] args)throws Exception{ BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); String str=null; while((str=reader.readLine())!=null){ System.out.println(isIP(str)?"YES":"NO"); } } public static boolean isIP(String str){ for(int i=0;i<str.length();i++){ char temp=str.charAt(i); if(temp!='.'&&(temp<'0'||temp>'9')){ return false; } } String[] s=str.split("\\."); return (Integer.valueOf(s[0])>=0&&Integer.valueOf(s[0])<=255)&& (Integer.valueOf(s[1])>=0&&Integer.valueOf(s[1])<=255)&& (Integer.valueOf(s[2])>=0&&Integer.valueOf(s[2])<=255)&& (Integer.valueOf(s[3])>=0&&Integer.valueOf(s[3])<=255); } }