MediumStringBit ManipulationUpdated Sep 2026

751. IP to CIDR

Asked at Databricks, OpenAI

Difficulty

Medium

Time

O(n)

Space

O(1)

Pattern

String

Companies

2

Problem

You are given a start IPv4 address ip and a count n. Think of every IPv4 address as a 32-bit number. The addresses you must cover are exactly the n addresses in the inclusive range from ip to ip + n - 1.

A CIDR block is written as base/prefix, where prefix is a number k from 0 to 32. It covers every address whose first k bits equal the first k bits of base. So a block with prefix k always covers exactly 2^(32-k) addresses, and its base must be aligned: the last 32-k bits of the base are all zero.

Return the shortest list of CIDR blocks that covers the range exactly — every address in the range is covered, and no address outside the range is covered. If several shortest lists exist, any one of them is accepted.

Cover 10 addresses with aligned blocks only

addresses8 aligned addresses78910111213141516Only the middle 8 addresses (8..15) form a clean aligned group; 7 and 16 standalone.
The range 255.0.0.7 to 255.0.0.16 must be split into blocks whose start is aligned to their own size.

Constraints

  • ●7 <= ip.length <= 15
  • ●ip is a valid IPv4 address "a.b.c.d" with each part in [0, 255]
  • ●1 <= n <= 1000
  • ●Every implied address ip + x for x < n is a valid IPv4 address

Examples

Example 1
Inputip = "255.0.0.7", n = 10
Output["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
WhyThe range is 255.0.0.7 through 255.0.0.16. The address 7 is odd, so no block bigger than size 1 can start there: /32. The address 8 is divisible by 8, so a /29 block (8 addresses, 8..15) fits perfectly. The last address 16 is again odd, so it needs its own /32. A bigger block like 255.0.0.0/28 would
Example 2
Inputip = "117.145.102.62", n = 8
Output["117.145.102.62/31","117.145.102.64/30","117.145.102.68/31"]
WhyThe range is 62 through 69. Address 62 is even but not divisible by 4, so the largest aligned block is size 2: /31 covers 62 and 63. Address 64 is divisible by 4, so /30 covers 64..67. Address 68 is only divisible by 2, so /31 covers 68 and 69.

Asked At

2 companies
CompanyDifficulty
DatabricksMediumView all Databricks questions →
OpenAIMediumView all OpenAI questions →

How to Think About It

1

Key insight: convert the IP to a 32-bit integer. The CIDR block size is determined by the trailing zeros in the binary representation. A block of size 2^k covers IPs from (ip & ~(2^k-1)) to (ip & ~(2^k-1)) + 2^k - 1.

2

Algorithm: while numIps > 0:
- Convert start IP to integer.
- Find the number of trailing zeros in start (call it tz).
- The maximum block size is 2^tz, but also limited by numIps.
- Find the largest power of 2 <= min(2^tz, numIps). Call it blockSize.
- The CIDR prefix length = 32 - log2(blockSize).
- Add the CIDR block to result.
`- Advance start by blockSize. Decrement numIps by blockSize.

3

Converting IP to integer: "a.b.c.d" = a2^24 + b2^16 + c*2^8 + d. Use int.from_bytes or manual bit shifting.
Converting integer to IP: shift and mask. (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, etc.

4

The trailing zeros trick: use ip & (-ip) to isolate the lowest set bit. The block size is the minimum of this value and the remaining IPs. This avoids computing log2 manually.

5

Edge cases: start IP at the boundary of a block (e.g., 0.0.0.0 with trailing zeros = 32), numIps = 0 (return empty list), numIps larger than remaining block (split into multiple blocks).

Optimal Approach

Convert start IP to a 32-bit integer. While numIps > 0:

  1. Find the number of trailing zeros in start: tz = trailingZeros(start). If start is 0, tz = 32.
  2. The maximum block size from trailing zeros is 1 << tz.
  3. The actual block size is the largest power of 2 that fits: blockSize = min(1 << tz, largestPowerOf2 <= numIps).
  4. Calculate prefix length: 32 - log2(blockSize).
  5. Add integerToIP(start)/prefixLength to result.
  6. start += blockSize. numIps -= blockSize.

To find the largest power of 2 <= n: use n & (-n) to get the lowest set bit, or use bit_length.

Time: O(numIps) in the worst case (many /32 blocks). Space: O(1) for output.

Greedy: take the biggest aligned block that fits

start = 255.0.0.7, n = 107 is odd → block size 1 → /32start = 8, n = 98 has 3 trailing zeros → size 8 → /29start = 16, n = 1 → /32Each step consumes one aligned block and shrinks theremaining range.block = min(1 << trailingZeros(start), largestPow2 <= n)prefix = 32 - log2(block)start += block; n -= block
At each step, look at the current address, find how many trailing zero bits it has, and take the largest power of two that fits both the alignment and the remaining count.
ComplexityTime O(n)Space O(1)In the worst case (all odd addresses) the loop runs once per address, so it is O(n) iterations; the output list itself holds up to n blocks.

What Trips People Up in Real Interviews

1

Forgetting that the block size must be a power of 2. You cannot use arbitrary sizes. The CIDR notation inherently means the block size is 2^(32-prefix). Always round down to the nearest power of 2.

2

Off-by-one in the prefix calculation. A block of size 2^k has prefix 32-k. So size 1 = /32, size 2 = /31, size 4 = /30, etc. Don't confuse the number of addresses with the prefix length.

3

Not handling the case where numIps exceeds the remaining block. If the start IP is at the boundary of a /29 block (size 8) but you only need 3 more IPs, use a smaller block that covers exactly 3 IPs (round down to power of 2).

4

Using floating point for log2 and getting precision errors. Use integer bit operations instead. block.bit_length() - 1 gives log2 for powers of 2. Avoid math.log2 for IP calculations.

5

Converting IP to integer incorrectly. The formula is a*2^24 + b*2^16 + c*2^8 + d. Don't concatenate the octets as a string and parse as integer.

Solution Code

O(n) time
def ipToCIDR(ip, n):
    def ip_to_int(ip):
        parts = list(map(int, ip.split('.')))
        return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]

    def int_to_ip(num):
        return '.'.join(str((num >> (24 - 8 * i)) & 0xFF) for i in range(4))

    def trailing_zeros(x):
        if x == 0:
            return 32
        count = 0
        while x & 1 == 0:
            x >>= 1
            count += 1
        return count

    start = ip_to_int(ip)
    result = []

    while n > 0:
        tz = trailing_zeros(start)
        max_block = 1 << tz
        block = max_block
        while block > n:
            block >>= 1
        prefix = 32 - (block.bit_length() - 1)
        result.append(f"{int_to_ip(start)}/{prefix}")
        start += block
        n -= block

    return result

Pro at DSA?

Test your skills with a real FAANG-style mock interview.

Start a Mock Interview →

Frequently Asked Questions

What is the IP to CIDR problem?

Given a start IP address and a number of IPs to cover, return the minimum list of CIDR blocks that exactly covers the range. This tests your understanding of IP addresses, subnet masks, and binary representation.

How do you solve IP to CIDR?

The optimal approach runs in O(n) time and O(1) space. Scroll up to "Optimal Approach" for the step-by-step walkthrough, diagrams, and code in Python, C++ and Java.

What companies ask IP to CIDR?

IP to CIDR is asked at Databricks, OpenAI. It is a medium difficulty problem.

What are common mistakes on IP to CIDR?
  • Forgetting that the block size must be a power of 2. You cannot use arbitrary sizes. The CIDR notation inherently means the block size is 2^(32-prefix). Always round down to the nearest power of 2.
  • Off-by-one in the prefix calculation. A block of size 2^k has prefix 32-k. So size 1 = /32, size 2 = /31, size 4 = /30, etc. Don't confuse the number of addresses with the prefix length.
  • Not handling the case where numIps exceeds the remaining block. If the start IP is at the boundary of a /29 block (size 8) but you only need 3 more IPs, use a smaller block that covers exactly 3 IPs (round down to power of 2).
  • Using floating point for log2 and getting precision errors. Use integer bit operations instead. `block.bit_length() - 1` gives log2 for powers of 2. Avoid `math.log2` for IP calculations.
  • Converting IP to integer incorrectly. The formula is `a*2^24 + b*2^16 + c*2^8 + d`. Don't concatenate the octets as a string and parse as integer.