leetcode-751. IP to CIDR

751IP to CIDR

Given a start IP address ip and a number of ips we need to cover n, return a representation of the range as a list (of smallest possible length) of CIDR blocks.

A CIDR block is a string consisting of an IP, followed by a slash, and then the prefix length. For example: "123.45.67.89/20". That prefix length "20" represents the number of common prefix bits in the specified range.

Example 1:

Input: ip = "255.0.0.7", n = 10
Output: ["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
Explanation:
The initial ip address, when converted to binary, looks like this (spaces added for clarity):
255.0.0.7 -> 11111111 00000000 00000000 00000111
The address "255.0.0.7/32" specifies all addresses with a common prefix of 32 bits to the given address,
ie. just this one address.

The address "255.0.0.8/29" specifies all addresses with a common prefix of 29 bits to the given address:
255.0.0.8 -> 11111111 00000000 00000000 00001000
Addresses with common prefix of 29 bits are:
11111111 00000000 00000000 00001000
11111111 00000000 00000000 00001001
11111111 00000000 00000000 00001010
11111111 00000000 00000000 00001011
11111111 00000000 00000000 00001100
11111111 00000000 00000000 00001101
11111111 00000000 00000000 00001110
11111111 00000000 00000000 00001111

The address "255.0.0.16/32" specifies all addresses with a common prefix of 32 bits to the given address,
ie. just 11111111 00000000 00000000 00010000.

In total, the answer specifies the range of 10 ips starting with the address 255.0.0.7 .

There were other representations, such as:
["255.0.0.7/32","255.0.0.8/30", "255.0.0.12/30", "255.0.0.16/32"],
but our answer was the shortest possible.

Also note that a representation beginning with say, "255.0.0.7/30" would be incorrect,
because it includes addresses like 255.0.0.4 = 11111111 00000000 00000000 00000100 
that are outside the specified range.

Note:

  1. ip will be a valid IPv4 address.
  2. Every implied address ip + x (for x < n) will be a valid IPv4 address.
  3. n will be an integer in the range [1, 1000].

此题做于 leetcode Weekly Contest 64

题意:

题目有点绕,给定一个起始ip地址,一个范围n。返回一个列表表示的最小ip地址块,包含以给定的起始ip为起点的,n个ip地址的ip。例:

Input: ip = "255.0.0.7", n = 10
Output: ["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
//255.0.0.7/32表示1个IP地址
//255.0.0.8/29表示8个IP地址
//255.0.0.16/32表示1个IP地址


思路:

本题在做weekly contest时,并没有做出来,以下代码也是别人的,我看过之后,写了自己的注释。 
有一些建议: 
做本题需要一些IP地址的知识,还要理解 16 行的x&-x 操作的含义

!最好自己先思考一下,对基本的可能出现的情况有一个了解。 
比如IP地址的最后一块是奇数/偶数的情况;IP地址块扩大时能容纳的数量和n的关系等。

class Solution {
    public  List<String> ipToCIDR(java.lang.String ip, int range) {
        long x = 0;
        //获得一个ip地址每一部分
        String[] ips = ip.split("\\.");
        //将整ip地址看为一个整体,求出整体的int表示
        for (int i = 0; i < ips.length; ++i) {
            x = Integer.parseInt(ips[i]) + x * 256;
        }
        List<String> ans = new ArrayList<>();
        while (range > 0) {
            //求出二进制表示下的最低有效位的位数能表示的地址的数量
            //如果为奇数,则=1,即以原单个起始ip地址为第一块
            //如果为偶数,则二进制表示下的最低有效位的位数能表示的地址的数量
            long step = x & -x;
            //如果大于range,则需要缩小范围
            while (step > range) step /= 2;
            //不大于需要的range,开始处理
            //求出现在能表示的step个地址的地址块
            ans.add(longToIP(x, (int)step));
            //x加上以求出的地址块
            x += step;
            //range减去以表示的地址块
            range -= step;
        }//直到range<0
        return ans;
    }
    static String longToIP(long x, int step) {
        int[] ans = new int[4];
        //&255操作求出后8位十进制表示
        ans[0] = (int) (x & 255);
        //右移8位,即求下一个块
        x >>= 8;
        ans[1] = (int) (x & 255);
        x >>= 8;
        ans[2] = (int) (x & 255);
        x >>= 8;
        ans[3] = (int) x;
        int len = 33;
        //每一位就可以表示2个
        while (step > 0) {
            len --;
            step /= 2;
        }
        return ans[3] + "." + ans[2] + "." + ans[1] + "." + ans[0] + "/" + len;
    }
}



转载于:https://www.cnblogs.com/linkcode/p/8150731.html

### 关于CIDR地址划分的练习题学习资料 #### CIDR地址划分概述 无类别域间路由(Classless Inter-Domain Routing, CIDR)是一种用于分配IP地址并实现更灵活网络设计的方法。通过使用斜杠记法来指定前缀长度,可以有效地管理IPv4和IPv6中的IP地址资源。 对于给定的CIDR地址块 `200.56.168.0/21`: - **二进制表示** 将十进制形式转换成二进制形式如下所示: - `200` 转换成二进制为 `11001000` - `56` 转换成二进制为 `00111000` - `168` 转换成二进制为 `10101000` - `/21` 表明有21位作为网络部分 因此整个CIDR地址块可以用二进制表示为:`11001000.00111000.10101xxx.xxxxxxxx`[^1] - **C类地址数量计算** 对于一个标准的C类地址,默认子网掩码为24位。而在这个例子中,由于采用了/21的形式,则意味着额外借用了三个比特位来进行更大范围内的寻址。因此,在这三位上能够形成的不同组合数即代表了可容纳多少个连续的C类地址空间的数量。 计算得出的结果是\(2^{3}=8\)个C类地址块被包含在此范围内。 ```python def calculate_c_class_blocks(prefix_length): """Calculate how many C-class blocks are included in a given prefix length.""" c_class_prefix = 24 extra_bits = c_class_prefix - prefix_length if extra_bits >= 0: return pow(2, abs(extra_bits)) raise ValueError("Prefix length cannot be greater than or equal to the classful boundary.") print(f"The number of C-class blocks is {calculate_c_class_blocks(21)}") ``` #### 推荐的学习材料练习题目 为了更好地理解和掌握CIDR的概念以及实际应用技巧,建议参考以下几方面的内容: - 阅读有关互联网协议版本四(IPv4)的技术文档,特别是那些讨论如何利用CIDR优化路由表大小的部分。 - 参加在线课程或观看视频教程,这些通常会提供直观的例子帮助理解抽象概念。 - 实践编程挑战网站上的相关问题集,比如LeetCode、HackerRank等平台都可能设有专门针对计算机网络主题的任务列表。 - 完整阅读关于CIDR地址块及其子网划分的相关章节[^2]。 - 解决更多类似的CIDR地址划分实例,如解析不同类型的CIDR表达式的含义,并尝试手动完成从点分十进制到二进制之间的相互转化过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值