题解 | #识别有效的IP地址和掩码并进行分类统计#

识别有效的IP地址和掩码并进行分类统计

http://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682

题目分析

  1. 题目给出了若干个IP地址和子网掩码的字符串
  2. 我们要根据给出的信息对这些IP和掩码进行划分工作,统计类型
  3. 一共要划分和统计的类型有7种,分别是A、B、C、D、E类IP地址的数量,错误IP或错误掩码的数量、私有IP的数量
  • 这是一个处理字符串的问题,思路其实比较简单,一点点抠细节处理清楚干净就好,但是细节很多比较麻烦。
  • 我们首先要分开IP和掩码,分别在puippripym函数中对公有IP、私有IP、掩码进行判断和分类
  • 大多数情况下只需要划分清楚,进行条件判断即可,但是对掩码判断我们提出两种解决方案

方法一:通过位运算处理掩码

  • 实现思路
    • 我们首先通过移位将掩码处理成32位的格式
    • 然后排除全0和全1的两种非法情况
    • 将掩码逐位右移,合法的情况应该是先读取到的一部分全部是0
    • 然后当出现1之后,我们设置flag为1,以此表示0和1的界限
    • 如果再遍历的过程中出现0,则说明掩码非法,反之则说明掩码正确
import sys

res = [0,0,0,0,0,0,0]

def puip(ip):
    if 1 <= ip[0] <= 126:				# A类地址判断条件
        res[0] += 1
    elif 128 <= ip[0] <= 191:			# B类地址判断条件
        res[1] += 1
    elif 192 <= ip[0] <= 223:			# C类地址判断条件
        res[2] += 1
    elif 224 <= ip[0] <= 239:			# D类地址判断条件
        res[3] += 1
    elif 240 <= ip[0] <= 255:			# E类地址判断条件
        res[4] += 1
    return

def prip(ip):			# 私有IP地址判断条件
    if (ip[0] == 10) or (ip[0] == 172 and 16 <= ip[1] <= 32) or (ip[0] == 192 and ip[1] == 168):
        res[6] += 1
    return

def ym(msk):			# 判断掩码合法性
    val = (msk[0] << 24) + (msk[1] << 16) + (msk[2] << 8) + msk[3]		# 转换成32位
    if val == 0:														  # 排除全0的情况
        return False
    if (val+1) == (1<<32):												# 排除全1的情况
        return False
    flag = 0
    while(val):
        digit = val & 1													# 逐位判断
        if digit == 1:
            flag = 1
        if flag == 1 and digit == 0:									# flag=1表示已经不允许再出现0
            return False
        val >>= 1
    return True
    

def judge(line):
    ip, msk = line.strip().split('~')
    ips = [int(x) for x in filter(None, ip.split('.'))]				# 获得表示IP的列表,理论上应该包含四个元素
    msks = [int(x) for x in filter(None, msk.split('.'))]			# 获得表示掩码的列表,理论上应该包含四个元素
    if ips[0] == 0 or ips[0] == 127:								# 排除非法IP不计数
        return
    if len(ips) < 4 or len(msks) < 4:								  # 判断错误掩码或错误IP
        res[5] += 1
        return
    if ym(msks) == True:											# 通过掩码判断的可以进行IP判断
        puip(ips)
        prip(ips)
    else:
        res[5] += 1
    return

for line in sys.stdin:
    judge(line)
# judge("192.168.0.2~255.255.255.0")

res = [str(x) for x in res]
print(" ".join(res))

复杂度分析

  • 时间复杂度:O(n)O(n),对所有的字符串都需要完全遍历一遍
  • 空间复杂度:O(n)O(n),存储IP和掩码所需要的额外空间申请

方法二:通过字符串索引处理掩码

  • 实现思路
    • 我们直接将掩码转换为32位字符串
    • 合法掩码规则是全部非0且全部非1,并且连续的1之后只能出现连续的0
    • 因此在字符串看来,0和1的分解点的索引是只差1的
    • 所以我们从左到右找到第一个0出现的位置,从右到左找到第一个1出现的位置
    • 根据两者相差的位置来判断掩码是否合法

alt

import sys

res = [0,0,0,0,0,0,0]

def puip(ip):
    if 1 <= ip[0] <= 126:				# A类地址判断条件
        res[0] += 1
    elif 128 <= ip[0] <= 191:			# B类地址判断条件
        res[1] += 1
    elif 192 <= ip[0] <= 223:			# C类地址判断条件
        res[2] += 1
    elif 224 <= ip[0] <= 239:			# D类地址判断条件
        res[3] += 1
    elif 240 <= ip[0] <= 255:			# E类地址判断条件
        res[4] += 1
    return

def prip(ip):			# 私有IP地址判断条件
    if (ip[0] == 10) or (ip[0] == 172 and 16 <= ip[1] <= 32) or (ip[0] == 192 and ip[1] == 168):
        res[6] += 1
    return

def ym(msk):
    val = (msk[0] << 24) + (msk[1] << 16) + (msk[2] << 8) + msk[3]	# 获取32位的掩码表示
    s = bin(val)[2:]												  # 去除“0b”字符,并转换成字符串
    pos0 = s.find('0')												  # 从左往右找到0第一次出现的位置 
    pos1 = s.rfind('1')												  # 从右往左找到1第一次出现的位置
    if pos0 != -1 and pos1 != -1 and pos0 - pos1 == 1:				  # 判断两个位置是否相差1,且是否找不到
        return True
    return False
    

def judge(line):
    ip, msk = line.strip().split('~')
    ips = [int(x) for x in filter(None, ip.split('.'))]				# 获得表示IP的列表,理论上应该包含四个元素
    msks = [int(x) for x in filter(None, msk.split('.'))]			# 获得表示掩码的列表,理论上应该包含四个元素
    if ips[0] == 0 or ips[0] == 127:								# 排除非法IP不计数
        return
    if len(ips) < 4 or len(msks) < 4:								  # 判断错误掩码或错误IP
        res[5] += 1
        return
    if ym(msks) == True:											# 通过掩码判断的可以进行IP判断
        puip(ips)
        prip(ips)
    else:
        res[5] += 1
    return

for line in sys.stdin:
    judge(line)
# judge("192.168.0.2~255.255.255.0")

res = [str(x) for x in res]
print(" ".join(res))


复杂度分析

  • 时间复杂度:O(n)O(n),对所有的字符串都需要完全遍历一遍
  • 空间复杂度:O(n)O(n),存储IP和掩码所需要的额外空间申请
全部评论

相关推荐

避坑恶心到我了大家好,今天我想跟大家聊聊我在成都千子成智能科技有限公司(以下简称千子成)的求职经历,希望能给大家一些参考。千子成的母公司是“同创主悦”,主要经营各种产品,比如菜刀、POS机、电话卡等等。听起来是不是有点像地推销售公司?没错,就是那种类型的公司。我当时刚毕业,急需一份临时工作,所以在BOSS上看到了千子成的招聘信息。他们承诺无责底薪5000元,还包住宿,这吸引了我。面试的时候,HR也说了同样的话,感觉挺靠谱的。于是,我满怀期待地等待结果。结果出来后,我通过了面试,第二天就收到了试岗通知。试岗的内容就是地推销售,公司划定一个区域,然后你就得见人就问,问店铺、问路人,一直问到他们有意向为止。如果他们有兴趣,你就得摇同事帮忙推动,促进成交。说说一天的工作安排吧。工作时间是从早上8:30到晚上18:30。早上7点有人叫你起床,收拾后去公司,然后唱歌跳舞(销售公司都这样),7:55早课(类似宣誓),8:05同事间联系销售话术,8:15分享销售技巧,8:30经理训话。9:20左右从公司下市场,公交、地铁、自行车自费。到了市场大概10点左右,开始地推工作。中午吃饭时间大约是12:00,公司附近的路边盖饭面馆店自费AA,吃饭时间大约40分钟左右。吃完饭后继续地推工作,没有所谓的固定中午午休时间。下午6点下班后返回公司,不能直接下班,需要与同事交流话术,经理讲话洗脑。正常情况下9点下班。整个上班的一天中,早上到公司就是站着的,到晚上下班前都是站着。每天步数2万步以上。公司员工没有自己的工位,百来号人挤在一个20平方米的空间里听经理洗脑。白天就在市场上奔波,公司的投入成本几乎只有租金和工资,没有中央空调。早上2小时,晚上加班2小时,纯蒸桑拿。没有任何福利,节假日也没有3倍工资之类的。偶尔会有冲的酸梅汤和西瓜什么的。公司的晋升路径也很有意思:新人—组长—领队—主管—副经理—经理。要求是业绩和团队人数,类似传销模式,把人留下来。新人不能加微信、不能吐槽公司、不能有负面情绪、不能谈恋爱、不能说累。在公司没有任何坐的地方,不能依墙而坐。早上吃早饭在公司外面的安全通道,未到上班时间还会让你吃快些不能磨蹭。总之就是想榨干你。复试的时候,带你的师傅会给你营造一个钱多事少离家近的工作氛围,吹嘘工资有多高、还能吹自己毕业于好大学。然后让你早点来公司、无偿加班、抓住你可能不会走的心思进一步压榨你。总之,大家在找工作的时候一定要擦亮眼睛,避免踩坑!———来自网友
qq乃乃好喝到咩噗茶:不要做没有专业门槛的工作
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
06-21 11:33
昨天是学校最后一场招聘会,鼠鼠去参加了,全场只有一个招聘java的岗位,上来先做一份笔试题,做完后他拿张纸对答案,然后开始问简历上的问题,深圳小厂,6-8k(题目如下),后面还有两轮面试。然后我就在招聘现场逛呀逛,看到有公司招聘电商运营,给的比上年的小厂还多,鼠鼠就去了解了下,然后hr跟鼠鼠要了份简历,虽然我的简历上面全是求职Java开发相关的内容,但是hr还是鼓励我说没关系,她帮我把简历给老板看看,下周一会给我通知。招聘会结束后鼠鼠想了一段时间,也和朋友聊了聊,发现我可能是不太适合这个方向,然后就跟爸爸说回家了给我发条微信,我有些话想跟他说说。晚上爸爸到家了,跟我发了条微信,我立马跑出图书馆跟他打起了电话,这个通话长达一个小时,主要是跟爸爸坦白说我不想找这行了,是你的儿子太没用了,想试试其他行业。然后爸爸也跟我说了很多,说他从来没有希望我毕业后就赚大钱的想法,找不到就回家去,回家了再慢慢找,实在找不到就跟他干(帮别人装修房子,个体户),他也知道工作不好找,让我不要那么焦虑,然后就是聊一些家常琐事。对于后面的求职者呢我有点建议想提一下,就是如果招实习的时间或者秋招开始,而你的简历又很差的情况下,不要说等做好项目填充完简历之后再投,那样就太晚了,建议先把熟悉的项目写上简历,然后边投边面边完善,求职是一个人进步的过程,本来就比别人慢,等到一切都准备好后再投岂不是黄花菜都凉了。时间够的话还是建议敲一遍代码,因为那样能让你加深一下对项目的理解,上面那些说法只是针对时间不够的情况。当然,这些建议可能没啥用,因为我只是一个loser,这些全是建立在我理想的情况下,有没有用还需其他人现身说法。上篇帖子没想到学校被人认了出来,为了不丢脸只能匿名处理了。
KPLACE:找研发类或技术类,主要还是要1.多投 2.多做准备,很多方面都要做准备 3.要有心理准备,投累了就休息一两天,再继续,要相信自己能找到
投递58到家等公司7个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务