列表

详情


751. IP 到 CIDR

IP地址 是一个格式化的 32位 无符号整数,每组 8位 被打印为一个十进制数字和,点字符 '.' 起到了分组的作用。

CIDR块 是一种用来表示一组特定IP地址的格式。字符串形式,由基础IP地址、斜杠和前缀长度 k 组成。它所覆盖的地址是所有IP地址的 k 与基础IP地址相同的IP地址。

给你一个起始IP地址 ip 和我们需要覆盖的IP地址数量 n 。你的目标是使用 尽可能少的CIDR块 来 覆盖范围 [ip, ip + n - 1] 内的所有IP地址 。不应该覆盖范围之外的其他IP地址。

返回 包含IP地址范围的 CIDR块最短 列表。如果有多个答案,返回其中 任何 一个 

 

示例 1:

输入:ip = "255.0.0.7", n = 10
输出:["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
解释:
需要覆盖的IP地址有:
- 255.0.0.7 -> 11111111 00000000 00000000 00000111
- 255.0.0.8 -> 11111111 00000000 00000000 00001000
- 255.0.0.9 -> 11111111 00000000 00000000 00001001
- 255.0.0.10 -> 11111111 00000000 00000000 00001010
- 255.0.0.11 -> 11111111 00000000 00000000 00001011
- 255.0.0.12 -> 11111111 00000000 00000000 00001100
- 255.0.0.13 -> 11111111 00000000 00000000 00001101
- 255.0.0.14 -> 11111111 00000000 00000000 00001110
- 255.0.0.15 -> 11111111 00000000 00000000 00001111
- 255.0.0.16 -> 11111111 00000000 00000000 00010000
CIDR区块“255.0.0.7/32”包含第一个地址。
CIDR区块255.0.0.8/29包含中间的8个地址(二进制格式为11111111 00000000 00000000 00001xxx)。
CIDR区块“255.0.0.16/32”包含最后一个地址。
请注意,虽然CIDR区块“255.0.0.0/28”覆盖了所有的地址,但它也包括范围之外的地址,所以我们不能使用它。

示例 2:

输入:ip = "117.145.102.62", n = 8
输出:["117.145.102.62/31","117.145.102.64/30","117.145.102.68/31"]

 

提示:

相似题目

复原 IP 地址

验证IP地址

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: vector<string> ipToCIDR(string ip, int n) { } };

golang 解法, 执行用时: 0 ms, 内存消耗: 2.2 MB, 提交时间: 2023-10-22 10:36:51

func ipToInt(ip string) int {
	ans := 0
	for _, s := range strings.Split(ip, ".") {
		x, _ := strconv.Atoi(s)
		ans = 256*ans + x
	}
	return ans
}
func intToIP(x int) string{
	ip:=""
	for i := 24; i >=0; i-=8 {
		ip+= strconv.Itoa((x >>i)%256)+"."
	}
	return ip[:len(ip)-1]
}
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
func bitLength(x int) int {
	if x == 0 {
		return 1
	}
	ans := 0
	for x > 0 {
		x >>= 1
		ans++
	}
	return ans
}

func ipToCIDR(ip string, n int) []string {
	start := ipToInt(ip)
	var ans []string
	for n > 0 {
		mask := max(33-bitLength(start&-start), 33-bitLength(n))
		if start==0{
			mask = 33-bitLength(n)
		}
		ans = append(ans, intToIP(start)+"/"+strconv.Itoa(mask))
		start += 1 << (32 - mask)
		n -= 1 << (32 - mask)
	}
	return ans
}

python3 解法, 执行用时: 52 ms, 内存消耗: 16.2 MB, 提交时间: 2023-10-22 10:36:09

from math import log2

class Solution:
    def ipToCIDR(self, ip: str, n: int) -> List[str]:

        def ip_to_int(ip):
            num = 0
            for x in ip.split('.'):
                num *= 256
                num += int(x)
            return num

        def int_to_ip(num):
            lst = []
            for _ in range(4):
                num, r = divmod(num, 256)
                lst.append(str(r))
            return '.'.join(lst[::-1])

        def low_bit(num):
            return num & (-num)

        res = []
        num = ip_to_int(ip)
        while n:
            count = low_bit(num) or 1024
            while count > n:
                count >>= 1
            res.append(int_to_ip(num) + '/' + str(32 - int(log2(count))))
            num += count
            n -= count
        return res

java 解法, 执行用时: 5 ms, 内存消耗: 40.6 MB, 提交时间: 2023-10-22 10:33:00

class Solution {
    public List<String> ipToCIDR (String ip,int n){
        int start = toInt(ip);//将ip转化为整数
        List<String> ans = new ArrayList<>();
        while (n > 0) {
            int trailingZeros = Integer.numberOfTrailingZeros(start);
            System.out.println(trailingZeros);
            int mask = 0, bitsInCIDR = 1;
            //计算mask
            while (bitsInCIDR < n && mask < trailingZeros) {
                bitsInCIDR <<= 1;
                mask++;
            }
            if (bitsInCIDR > n) {
                bitsInCIDR >>= 1;
                mask--;
            }

            ans.add(toString(start, 32 - mask));
            n -= bitsInCIDR;
            start += (bitsInCIDR);
        }
        return ans;
    }

    private String toString(int number, int range) {
        final int WORD_SIZE = 8;
        StringBuilder buffer = new StringBuilder();
        for (int i = 3; i >= 0; --i) {
            buffer.append(((number >> (i * WORD_SIZE)) & 255));
            buffer.append(".");
        }
        buffer.setLength(buffer.length() - 1);
        buffer.append("/").append(range);
        return buffer.toString();
    }

    private int toInt(String ip) {
        String[] strs = ip.split("\\.");
        int sum = 0;
        for (String str : strs) {
            sum *= 256;
            sum += Integer.parseInt(str);
        }
        return sum;
    }
}

上一题