LeetCode Solutions

751. IP to CIDR

Time: $O(\log n)$

Space: $O(\log n)$

			

class Solution {
 public:
  vector<string> ipToCIDR(string ip, int n) {
    vector<string> ans;
    long num = getNum(ip);

    while (n > 0) {
      const long lowbit = num & -num;
      const long count = lowbit == 0 ? maxLow(n) : firstFit(lowbit, n);
      ans.push_back(getCIDR(num, getPrefix(count)));
      n -= count;
      num += count;
    }

    return ans;
  }

 private:
  long getNum(const string& ip) {
    istringstream iss(ip);
    long num = 0;
    for (string token; getline(iss, token, '.');)
      num = num * 256 + stol(token);
    return num;
  }

  // Returns max i s.t. 2^i < n
  int maxLow(int n) {
    for (int i = 0; i < 32; ++i)
      if (1 << i + 1 > n)
        return 1 << i;
    throw;
  }

  long firstFit(long lowbit, long n) {
    while (lowbit > n)
      lowbit >>= 1;
    return lowbit;
  }

  string getCIDR(long num, long prefix) {
    const long d = num & 255;
    num >>= 8;
    const long c = num & 255;
    num >>= 8;
    const long b = num & 255;
    num >>= 8;
    const long a = num & 255;
    return to_string(a) + '.' + to_string(b) + '.' + to_string(c) + '.' +
           to_string(d) + '/' + to_string(prefix);
  }

  // E.g. count = 8 = 2^3 -> prefix = 32 - 3 = 29
  //      count = 1 = 2^0 -> prefix = 32 - 0 = 32
  int getPrefix(long count) {
    for (int i = 0; i < 32; ++i)
      if (count == 1 << i)
        return 32 - i;
    throw;
  }
};
			

class Solution {
  public List<String> ipToCIDR(String ip, int n) {
    List<String> ans = new ArrayList<>();
    long num = getNum(ip.split("\\."));

    while (n > 0) {
      final long lowbit = num & -num;
      final long count = lowbit == 0 ? maxLow(n) : firstFit(lowbit, n);
      ans.add(getCIDR(num, getPrefix(count)));
      n -= (int) count;
      num += count;
    }

    return ans;
  }

  private long getNum(String[] x) {
    long num = 0;
    for (int i = 0; i < 4; ++i)
      num = num * 256 + Long.parseLong(x[i]);
    return num;
  }

  // Returns max i s.t. 2^i < n
  private int maxLow(int n) {
    for (int i = 0; i < 32; ++i)
      if (1 << i + 1 > n)
        return 1 << i;
    throw new IllegalArgumentException();
  }

  private long firstFit(long lowbit, long n) {
    while (lowbit > n)
      lowbit >>= 1;
    return lowbit;
  }

  private String getCIDR(long num, long prefix) {
    final long d = num & 255;
    num >>= 8;
    final long c = num & 255;
    num >>= 8;
    final long b = num & 255;
    num >>= 8;
    final long a = num & 255;
    return new StringBuilder()
        .append(a)
        .append(".")
        .append(b)
        .append(".")
        .append(c)
        .append(".")
        .append(d)
        .append("/")
        .append(prefix)
        .toString();
  }

  // E.g. count = 8 = 2^3 -> prefix = 32 - 3 = 29
  //      count = 1 = 2^0 -> prefix = 32 - 0 = 32
  private int getPrefix(long count) {
    for (int i = 0; i < 32; ++i)
      if (count == 1 << i)
        return 32 - i;
    throw new IllegalArgumentException();
  }
}
			

class Solution:
  def ipToCIDR(self, ip: str, n: int) -> List[str]:
    ans = []
    num = self._getNum(ip.split('.'))

    while n > 0:
      lowbit = num & -num
      count = self._maxLow(n) if lowbit == 0 else self._firstFit(lowbit, n)
      ans.append(self._getCIDR(num, self._getPrefix(count)))
      n -= count
      num += count

    return ans

  def _getNum(self, x: List[str]) -> int:
    num = 0
    for i in range(4):
      num = num * 256 + int(x[i])
    return num

  # Returns max i s.t. 2^i < n
  def _maxLow(self, n: int) -> Optional[int]:
    for i in range(32):
      if 1 << i + 1 > n:
        return 1 << i

  def _firstFit(self, lowbit: int, n: int) -> int:
    while lowbit > n:
      lowbit >>= 1
    return lowbit

  def _getCIDR(self, num: int, prefix: int) -> str:
    d = num & 255
    num >>= 8
    c = num & 255
    num >>= 8
    b = num & 255
    num >>= 8
    a = num & 255
    return '.'.join([str(s) for s in [a, b, c, d]]) + '/' + str(prefix)

  # E.g. count = 8 = 2^3 . prefix = 32 - 3 = 29
  #      count = 1 = 2^0 . prefix = 32 - 0 = 32
  def _getPrefix(self, count: int) -> Optional[int]:
    for i in range(32):
      if count == 1 << i:
        return 32 - i