LeetCode | 751. IP to CIDR 分治法

Givena start IP address ip and a numberof ips we need to cover n, return a representation of the range as a list (of smallestpossible length) of CIDR blocks.

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

Example1:

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 likethis (spaces added for clarity):

255.0.0.7 -> 11111111 00000000 00000000 00000111

The address "255.0.0.7/32" specifies all addresseswith a common prefix of 32 bits to the given address,

ie. just this one address.

 

The address "255.0.0.8/29" specifies all addresseswith 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 addresseswith 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 startingwith 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 = 1111111100000000 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].

这题是真的难,题目的意思是给你一个ip地址,以及一个数字n,(这里需要注意,这里的n表示ip之后的n的Ip地址,包含给你的ip地址,因此实际上是取ip和ip之后的9个ip地址,以后做题的时候需要注意),然后让你将这个ip地址的范围切分成cidr地址,要求cidr的地址的数量最少,这题我觉得比很多hard的题目都要难了。

首先是怎样切分的问题,经过思考之后发现,每一个cidr地址都是2的倍数,因此可以从0到255.255.255.255不断的二分,然后不断的判断二分的范围和需要求得范围是否匹配,每次匹配都返回(一定要记得返回),就能得到最优的匹配方案,这其实是一个分治法,包含着贪心算法的思路,以后在做吧某个范围划分为多个范文,问你如何划分能够得到最少的划分范围类似这样的题目的时候,记得使用分治法去解决,

这里还涉及到一个string类型如何存储,如何装换成其他数据类型的问题,这里可以将stringIP地址转换成整形,也就是256进制的4位数,然后可以使用10进制表示,这种转换方法要记住,

然后假如使用整型来表示ip地址的话,就又设计到了一个整数范围的问题,这里需要注意,默认的int(32位)和(long)都是32位,都只能表示到21亿,用来表示ip地址的话会溢出,导致数值变成负数,以后在计算由ip地址转换成的整型的时候,记得使用Longlong类型,这样才不会导致问题,以后在实在不确定变量的取值范围的时候可以查看INT_MAX常亮和LONG_MAX常量,这样能够直接得到各个变量的取值范围,以后在直接把数值赋给变量的时候要记住,123123这样直接写默认是int类型,在计算之后特别是除法计算的时候可能会导致问题,将它计算后假如计算的结果越界了也可能会导致问题,特别是需要将计算后的常量赋给long long 的时候,所有以后在使用数字常量的时候记得区分123,123l,123ll,123.0,123,0f这些的区别!

class Solution {

public:

   long long ipToLong(string ip)

{

      int start = 0; long long result = 0;

      string tmp;

      for (int i = 0; i < 3; i++)

      {

            tmp = ip.substr(start,ip.find_first_of('.', start) -start);

            result = result * 256 +atoll(tmp.c_str());

            start = ip.find_first_of('.',start)+1;

      }

      tmp = ip.substr(start,ip.find_first_of(start, ip.size()));

      result = result * 256 + atol(tmp.c_str());

      return result;

}

int digit(longlong num)

{

      num += 1; int count = 0;

      while (num > 1)

      {

            num /= 2; count++;

      }

      return count;

}

stringlongToIp(long long num)

{

      string tmp = "";

      for (int i = 0; i < 3; i++)

      { 

            tmp =  "." + to_string(num % 256ll)+tmp;

            num /= 256;

      }

      tmp =to_string(num % 256) + tmp;

      return tmp;

}

void query(longlong l, long long r, long long ll, long long rr, vector<string>&result)

{

      if (l == ll&&r == rr)

      {

            result.push_back(longToIp(ll) +"/" + to_string(32 - digit(rr - ll))); return;

      }

      long long m = (ll + rr) / 2;

     

      if (l <= m&&r > m)

      {

            query(l, m, ll, m, result);

            query(m+1, r, m+1,rr, result);

      }

      if (r <= m)

      {

            query(l, r, ll, m, result);

      }

      if (l > m)

      {

            query(l, r, m+1, rr, result);

      }

}

vector<string>ipToCIDR(string ip, int range) {

      long long l, ll, r, rr;

      ll = 0;

      rr = 256ll * 256ll * 256ll * 256ll - 1;

 

      l = ipToLong(ip);

      r = l + range-1;

 

      vector<string>result;

      query(l, r, ll, rr, result);

      return result;

}

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值