码迷,mamicode.com
首页 > 其他好文 > 详细

二分查找(下):如何快速定位IP对应的省份地址?

时间:2020-02-18 13:14:32      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:变形   span   有序数组   mamicode   预处理   public   排序   实现   二分查找   

问题

假设我们有 12 万条这样的 IP 区间与归属地的对应关系,如何快速定位出一个 IP 地址的归属地呢?

二分查找的变形

技术图片

 

 变体一:查找第一个值等于给定值的元素

 1 public int bsearch(int[] a, int n, int value) {
 2   int low = 0;
 3   int high = n - 1;
 4   while (low <= high) {
 5     int mid = low + ((high - low) >> 1);
 6     if (a[mid] >= value) {
 7       high = mid - 1;
 8     } else {
 9       low = mid + 1;
10     }
11   }
12 
13   if (low < n && a[low]==value) return low;
14   else return -1;
15 }

换了一种实现方法

 1 public int bsearch(int[] a, int n, int value) {
 2   int low = 0;
 3   int high = n - 1;
 4   while (low <= high) {
 5     int mid =  low + ((high - low) >> 1);
 6     if (a[mid] > value) {
 7       high = mid - 1;
 8     } else if (a[mid] < value) {
 9       low = mid + 1;
10     } else {
11       if ((mid == 0) || (a[mid - 1] != value)) return mid;
12       else high = mid - 1;
13     }
14   }
15   return -1;
16 }

a[mid]跟要查找的 value 的大小关系有三种情况:大于、小于、等于。对于 a[mid]>value 的情况,我们需要更新 high= mid-1;对于 a[mid]<value 的情况,我们需要更新 low=mid+1

 

变体二:查找最后一个值等于给定值的元素

 1 public int bsearch(int[] a, int n, int value) {
 2   int low = 0;
 3   int high = n - 1;
 4   while (low <= high) {
 5     int mid =  low + ((high - low) >> 1);
 6     if (a[mid] > value) {
 7       high = mid - 1;
 8     } else if (a[mid] < value) {
 9       low = mid + 1;
10     } else {
11       if ((mid == n - 1) || (a[mid + 1] != value)) return mid;
12       else low = mid + 1;
13     }
14   }
15   return -1;
16 }

变体三:查找第一个大于等于给定值的元素

 1 public int bsearch(int[] a, int n, int value) {
 2   int low = 0;
 3   int high = n - 1;
 4   while (low <= high) {
 5     int mid =  low + ((high - low) >> 1);
 6     if (a[mid] >= value) {
 7       if ((mid == 0) || (a[mid - 1] < value)) return mid;
 8       else high = mid - 1;
 9     } else {
10       low = mid + 1;
11     }
12   }
13   return -1;
14 }

变体四:查找最后一个小于等于给定值的元素

 1 public int bsearch7(int[] a, int n, int value) {
 2   int low = 0;
 3   int high = n - 1;
 4   while (low <= high) {
 5     int mid =  low + ((high - low) >> 1);
 6     if (a[mid] > value) {
 7       high = mid - 1;
 8     } else {
 9       if ((mid == n - 1) || (a[mid + 1] > value)) return mid;
10       else low = mid + 1;
11     }
12   }
13   return -1;
14 }

问题解决分析

1. 如果 IP 区间与归属地的对应关系不经常更新,我们可以先预处理这 12 万条数据,让其按照起始 IP 从小到大排序。如何来排序呢?我们知道,IP 地址可以转化为 32 位的整型数。所以,我们可以将起始地址,按照对应的整型值的大小关系,从小到大进行排序。

2. 然后,这个问题就可以转化为我刚讲的第四种变形问题“在有序数组中,查找最后一个小于等于某个给定值的元素”了

3. 当我们要查询某个 IP 归属地时,我们可以先通过二分查找,找到最后一个起始 IP 小于等于这个 IP 的 IP 区间,然后,检查这个 IP 是否在这个 IP 区间内,如果在,我们就取出对应的归属地显示;如果不在,就返回未查找到

二分查找(下):如何快速定位IP对应的省份地址?

标签:变形   span   有序数组   mamicode   预处理   public   排序   实现   二分查找   

原文地址:https://www.cnblogs.com/mysky007/p/12325537.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!