华为笔试机考-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);
}
}
查看6道真题和解析