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

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

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

思路

这道题本质并不复杂,只是细节比较多,需要规划好校验判断的路线

因为判断IP合法过程需要拆分字符串转int数组,考虑到判断后还需要继续分析其int值是否符合范围要求

若是重复split,不可避免出现代码copy的bad smell

因此应该将合法IP的int数组保存下来

但是单纯判断IP合法并不能充分说明这个IP就一定要进入后面的判断过程

比如子网掩码不合法、开头为0或者127

为此定义一个游标cursor,我们认为游标之前的IP是有效的

具体步骤

  1. 接收数据

  2. 校验数据

    • 校验是否合法IP
      • 若是合法IP,则储存下来,但是注意cursor先不要右移
    • 若是合法IP,且开头为0或127,则continue,不计入任何计数
    • 校验是否合法子网掩码
    • 若同时满足合法IP+合法子网掩码,才将cursor右移;否则计入错误IP地址数量
  3. 统计数据

    • 遍历cursor之前的所有IP地址,按A~E类分别比对判断

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * HJ18 识别有效的IP地址和掩码并进行分类统计
 */
public class Main {
    public static void main(String[] args) {

        List<String> data = loadDataFromScanner();
//        List<String> data = loadTestData();

        Analyser analyser = new Analyser(data);
        analyser.doAnalyse();
        System.out.println(analyser.report());
    }

    private static List<String> loadDataFromScanner() {
        List<String> data = new ArrayList<>();

        Scanner sc = new Scanner(System.in);
        while (sc.hasNextLine()) {
            data.add(sc.nextLine());
        }

        return data;
    }


    public static class Analyser {
        private int a;
        private int b;
        private int c;
        private int d;
        private int e;
        private int err;
        private int self;
        private List<String> data;
        private List<int[]> ipAddresses;
        private int ipAddressCursor;

        public Analyser(List<String> data) {
            this.data = data;
        }

        public void doAnalyse() {
            init();

            for (String s : data) {
                String[] arr = s.split("~");
                String ip = arr[0];
                String mask = arr[1];

                boolean legalIp = isLegalIp(ip);
                if (legalIp) {
                    int first = ipAddresses.get(ipAddressCursor)[0];
                    if (first == 0 || first == 127) {
                        // 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略
                        continue;
                    }
                }

                boolean legalMask = isLegalMask(mask);

                if (legalIp && legalMask) {
                    ++ipAddressCursor;
                } else {
//                    System.out.println(String.format("legalIp: %s, legalMask: %s %s", legalIp, legalMask, s));
                    ++err;
                }
            }

            for (int i = 0; i < ipAddressCursor; i++) {
                int[] ipArr = ipAddresses.get(i);
                if (isPrivateIp(ipArr)) {
                    ++self;
                }

                int first = ipArr[0];

                if (first <= 126) {
                    ++a;
                } else if (first <= 191) {
                    ++b;
                } else if (first <= 223) {
                    ++c;
                } else if (first <= 239) {
                    ++d;
                } else if (first <= 255) {
                    ++e;
                }
            }
        }

        private boolean isPrivateIp(int[] ip) {
            if (ip[0] == 10) {
                return true;
            } else if (ip[0] == 172) {
                if (ip[1] >= 16 && ip[1] <= 31) {
                    return true;
                }
            } else if (ip[0] == 192 && ip[1] == 168) {
                return true;
            }

            return false;
        }

        private boolean isLegalMask(String mask) {
            String[] maskStr = mask.split("\\.");
            if (maskStr.length != 4) {
                return false;
            }

            boolean headOne = true;
            for (String s : maskStr) {
                switch (s) {
                    case "255":
                        if (!headOne) {
                            return false;
                        }
                        break;
                    case "254":
                    case "252":
                    case "248":
                    case "240":
                    case "224":
                    case "192":
                    case "128":
                        if (!headOne) {
                            return false;
                        }
                        headOne = false;
                        break;
                    case "0":
                        if (headOne) {
                            headOne = false;
                        }
                        break;
                    default:
                        return false;
                }
            }
            return !headOne;
        }

        private boolean isLegalIp(String ip) {
            String[] ipStr = ip.split("\\.");
            if (ipStr.length != 4) {
                return false;
            }
            int[] ipInt = new int[4];
            for (int i = 0; i < 4; i++) {
                try {
                    ipInt[i] = Integer.parseInt(ipStr[i]);
                } catch (NumberFormatException ignore) {
                    return false;
                }
            }

            for (int i : ipInt) {
                if (i < 0 || i > 255) {
                    return false;
                }
            }

            saveIp(ipInt, ipAddressCursor);
            return true;
        }

        private void saveIp(int[] ipInt, int ipAddressCursor) {
            if (ipAddressCursor == ipAddresses.size()) {
                ipAddresses.add(ipInt);
            } else {
                ipAddresses.set(ipAddressCursor, ipInt);
            }

        }

        private void init() {
            this.a = 0;
            this.b = 0;
            this.c = 0;
            this.d = 0;
            this.e = 0;
            this.err = 0;
            this.self = 0;
            this.ipAddresses = new ArrayList<>();
            this.ipAddressCursor = 0;
        }

        public String report() {
            return String.format("%s %s %s %s %s %s %s", a, b, c, d, e, err, self);
        }
    }

    private static List<String> loadTestData() {
        List<String> data = new ArrayList<>();
        data.add("225.240.129.203~255.110.255.255");
        data.add("183.181.49.4~255.0.0.0");
        data.add("172.177.113.45~255.0.0.0");
        data.add("176.134.46.246~255.0.0.0");
        data.add("153.63.21.56~255.255.58.255");
        data.add("23.135.167.228~255.0.0.0");
        data.add("204.58.47.149~255.0.0.0");
        data.add("113.33.181.46~255.255.255.0");
        data.add("73.245.52.119~255.255.154.0");
        data.add("23.214.47.71~255.0.0.0");
        data.add("139.124.188.91~255.255.255.100");
        data.add("142.94.192.197~255.0.0.0");
        data.add("53.173.252.202~255.0.0.0");
        data.add("127.201.56.50~255.255.111.255");
        data.add("118.251.84.111~255.0.0.0");
        data.add("130.27.73.170~255.0.0.0");
        data.add("253.237.54.56~255.86.0.0");
        data.add("64.189.222.111~255.255.255.139");
        data.add("148.77.44.147~255.0.0.0");
        data.add("59.213.5.253~255.255.0.0");
        data.add("3.52.119.131~255.255.0.0");
        data.add("213.208.164.145~255.255.0.0");
        data.add("24.22.21.206~255.255.90.255");
        data.add("89.43.34.31~255.0.0.0");
        data.add("9.64.214.75~255.0.0.0");
        data.add("110.156.20.173~255.153.0.0");
        data.add("71.183.242.53~255.255.0.0");
        data.add("119.152.129.100~255.0.0.0");
        data.add("38.187.119.201~255.0.0.0");
        data.add("73.81.221.180~255.255.255.255");
        data.add("73.198.13.199~255.0.15.0");
        data.add("99.42.142.145~255.255.255.0");
        data.add("196.121.115.160~255.0.0.0");
        data.add("226.30.29.206~255.0.0.0");
        data.add("244.248.31.171~255.255.255.255");
        data.add("59.116.159.246~255.0.0.0");
        data.add("121.124.37.157~255.0.0.226");
        data.add("103.42.94.71~255.255.0.0");
        data.add("125.88.217.249~255.255.74.255");
        data.add("73.44.250.101~255.255.255.0");

        return data;
    }
}

全部评论

相关推荐

01-26 18:45
门头沟学院 Java
一天代码十万三:哥们实习再包一下吧,产出太笼统了,尽量体现业务
点赞 评论 收藏
分享
01-21 12:26
暨南大学 golang
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务