题解 | #判断两个IP是否属于同一子网#
判断两个IP是否属于同一子网
http://www.nowcoder.com/practice/34a597ee15eb4fa2b956f4c595f03218
题目的主要信息:
- 利用子网掩码可以判断两台主机是否中同一子网中。若两台主机的IP地址分别与它们的子网掩码相“与”后的结果相同,则说明这两台主机在同一子网中。
- 掩码与IP每一段在 0 - 255 之间。掩码的二进制字符串前缀为网络号,都由‘1’组成;后缀为主机号,都由'0'组成
方法一:
按照题目的思路求解。第一步是判断ip地址和掩码的格式是否合法,由题意可知,掩码与IP每一段在 0 - 255 之间,如果有字段小于0或者大于255则直接判为格式非法;若字段都在 0 - 255 之间,判断掩码是否前缀为1,后缀为0,根据归纳推理发现,若0<mask[i]<255,则第i段已经包含0了,那么从第i+1段开始必须全为0,因此若mask[i+1]>0,则格式非法。
格式都合法后,分别对两个ip地址逐段进行AND操作,若结果相同则输出0,否则输出2;
具体做法:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> mask(4,0);
vector<int> ip1(4,0);
vector<int> ip2(4,0);
char c;
while (cin>>mask[0]>>c>>mask[1]>>c>>mask[2]>>c>>mask[3])//输入掩码
{
int flag = -1;//结果
cin>>ip1[0]>>c>>ip1[1]>>c>>ip1[2]>>c>>ip1[3];//第一个ip地址
cin>>ip2[0]>>c>>ip2[1]>>c>>ip2[2]>>c>>ip2[3];//第二个ip地址
for(int i=0;i<4;i++)//两个ip地址和掩码每一段都要在0-255之间
{
if(mask[i]<0 || mask[i]>255 || ip1[i]<0 || ip1[i]>255 ||ip2[i]<0 || ip2[i]>255)
{
flag = 1;//格式非法
break;
}
}
for(int i=0;i<3;i++)//掩码的网络号全为1,主机号全为0
{
if(mask[i]<255 && mask[i+1]>0)
{
flag = 1;
break;
}
}
if(flag==1)//格式非法,输出1
{
cout<<flag<<endl;
}else{
for(int i=0;i<4;i++)
{
if((mask[i]&ip1[i])!=(mask[i]&ip2[i]))//两个ip地址和掩码做AND操作
{
flag = 2;
break;
}else{//AND操作结果不相同
flag = 0;
}
}
cout<<flag<<endl;
}
}
return 0;
}
复杂度分析:
- 时间复杂度:O(1),判断格式合法和进行与操作都只需要常数时间。
- 空间复杂度:O(1),只使用了常数空间。
方法二:
判断格式是否合法的时候可以用正则表达式来判断,((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d).){4}可以判断每个字段是否在0-255。首先把vector类型转换为string,再用regex_match函数和表达式进行匹配,若匹配返回true,否则返回false。进行格式非法判断的时候,用&&进行合并,只要有一个地址不合法,就返回1。
具体做法:
#include<iostream>
#include<vector>
#include<string>
#include<regex>
using namespace std;
int main()
{
vector<int> mask(4,0);
vector<int> ip1(4,0);
vector<int> ip2(4,0);
regex pattern("((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)\.){4}");//匹配0.0.0.0.-255.255.255.255.的正则表达式
char c;
while (cin>>mask[0]>>c>>mask[1]>>c>>mask[2]>>c>>mask[3])//输入掩码
{
int flag = -1;//结果
cin>>ip1[0]>>c>>ip1[1]>>c>>ip1[2]>>c>>ip1[3];//第一个ip地址
cin>>ip2[0]>>c>>ip2[1]>>c>>ip2[2]>>c>>ip2[3];//第二个ip地址
string str_mask,str_ip1,str_ip2;
for(int i=0;i<4;i++){
str_mask+=to_string(mask[i])+'.';
str_ip1+=to_string(ip1[i])+'.';
str_ip2+=to_string(ip2[i])+'.';
}
if((regex_match(str_mask,pattern)&®ex_match(str_ip1,pattern)&®ex_match(str_ip2,pattern))==false)
{
flag=1;
}
for(int i=0;i<3;i++)//掩码的网络号全为1,主机号全为0
{
if(mask[i]<255 && mask[i+1]>0)
{
flag = 1;
break;
}
}
if(flag==1)//格式非法,输出1
{
cout<<flag<<endl;
}else{
for(int i=0;i<4;i++)
{
if((mask[i]&ip1[i])!=(mask[i]&ip2[i]))//两个ip地址和掩码做AND操作
{
flag = 2;
break;
}else{//AND操作结果相同
flag = 0;
}
}
cout<<flag<<endl;
}
}
return 0;
}
复杂度分析:
- 时间复杂度:O(1),判断格式合法和进行与操作都只需要常数时间。
- 空间复杂度:O(1),只使用了常数空间。