zoukankan      html  css  js  c++  java
  • 如何快速定位出一个IP地址的归属地?——二分查找变体

    • 查找第一个值等于给定值的元素
    • 查找最后一个值等于给定值的元素
    • 查找第一个大于等于给定值的元素
    • 查找最后一个小于等于给定值的元素
    • 查找循环有序数组中等于给定值的元素
    #include <iostream>
    #include <vector>
    #include <stack>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <algorithm>
    #include "TreeNode.h"
    #include "ListNode.h"
    using namespace std;
    
    // 二分查找具有O(logn)的时间复杂度,很强,但是只能用于数组的数据结构,像链表就不适合
    
    // 二分查找非递归法
    int binarySearch(int num[], int length, int key){
        if(length < 1)
            return -1;
        int low = 0;
        int high = length - 1;
        int middle = 0;
        while(low <= high){
            // 以后尽量使用位运算,不直接用(low + high) / 2是为了防止加法溢出
            middle = low + ((high - low) >> 1);
            if(num[middle] == key)
                return middle;
            if(num[middle] > key)
                high = middle - 1;
            else if(num[middle] < key)
                low = middle + 1;
        }
        // 没找到则返回-1
        return -1;
    }
    
    // 二分查找递归方法
    int binarySearchPlus(int num[], int low, int high, int key){
        if(low > high)
            return -1;
        int middle = low + ((high - low) >> 1);
        if(num[middle] == key)
            return middle;
        if(num[middle] > key)
            return binarySearchPlus(num, low, middle - 1, key);
        else
            return binarySearchPlus(num, middle + 1, high, key);
    }
    
    // 排序数组中第一次出现k的位置
    int binarySearchFirst(vector<int> num, int k, int length){
        int low = 0;
        int high = length - 1;
        int middle = 0;
        while(low <= high){
            middle = low + ((high - low) >> 1);
            if(num[middle] == k){
                if(middle > 0 && num[middle - 1] != k || middle == 0)
                    return middle;
                else
                    high = middle - 1;
            }
            else if(num[middle] > k)
                high = middle - 1;
            else
                low = middle + 1;
        }
        return -1;
    }
    
    // 最后一次出现k的位置
    int binarySearchLast(vector<int> num, int k, int length){
        int low = 0;
        int high = length - 1;
        int middle = 0;
        while(low <= high){
            middle = low + ((high - low) >> 1);
            if(num[middle] == k){
                if(middle < length - 1 && num[middle + 1] != k || middle == length - 1)
                    return middle;
                else
                    low = middle + 1;
            }
            else if(num[middle] > k)
                high = middle - 1;
            else
                low = middle + 1;
        }
        return -1;
    }
    
    // 查找第一个大于等于给定值的元素(和大于不一样),妙啊
    int binarySearchFirstHighPlus(int num[], int length, int key){
        if(length < 1)
            return -1;
        int low = 0;
        int high = length - 1;
        int middle = 0;
        while(low <= high){
            middle = low + ((high - low) >> 1);
            if(num[middle] >= key){
                // 妙啊
                if(middle == 0 || num[middle - 1] < key)
                    return middle;
                else
                    // 往左走
                    high = middle - 1;
            }
            else
                low = middle + 1;
        }
        return -1;
    }
    
    // 查找第一个小于等于给定值的元素(和小于不一样),妙啊
    int binarySearchFirstLowPlus(int num[], int length, int key){
        if(length < 1)
            return -1;
        int low = 0;
        int high = length - 1;
        int middle = 0;
        while(low <= high){
            middle = low + ((high - low) >> 1);
            if(num[middle] <= key){
                if(middle == length - 1 || num[middle + 1] > key)
                    return middle;
                else
                    // 往右走
                    low = middle + 1;
            }
            else
                high = middle - 1;
        }
        return -1;
    }
    
    // 在循环有序数组中利用二分查找元素
    // 如果加大点儿难度,比如在循环有序数组中查找第一个等于某值的元素,比如在{3,4,5,6,1,2,3,4,5}中查找4
    int bsearchInCycleSortArray(int num[], int length, int key){
        if(length < 1)
            return -1;
        int low = 0;
        int high = length - 1;
        int middle = 0;
        while(low <= high){
            middle = low + ((high - low) >> 1);
            if(num[middle] == key)
                return middle;
            // 如果中间元素小于尾元素,说明右端是有序的,左端是循环的
            if(num[middle] < num[high]){
                // 如果目标元素在有序数组范围中,则后面的都是二分查找
                if(num[middle] < key && key <= num[high])
                    low = middle + 1;
                // 如果不在,则在另一半继续查找
                else
                    high = middle - 1;
            }
            // 如果中间元素大于尾元素,说明左端是有序的,右端是循环的
            else{
                // 如果目标元素在有序数组范围中,则后面的都是二分查找
                if(num[low] <= key && key < num[middle])
                    high = middle - 1;
                // 如果不在,则在另一半继续查找
                else
                    low = middle + 1;
            }
        }
        return -1;
    }
    
    int main(int argc, char* argv[]){
    
        int arr[6] = {4,5,6,1,2,3};
    
        cout<<bsearchInCycleSortArray(arr, 6, 2)<<endl;
        return 0;
    }
    
  • 相关阅读:
    SharePoint 2013 安装.NET Framework 3.5 报错
    SharePoint 2016 配置工作流环境
    SharePoint 2016 站点注册工作流服务报错
    Work Management Service application in SharePoint 2016
    SharePoint 2016 安装 Cumulative Update for Service Bus 1.0 (KB2799752)报错
    SharePoint 2016 工作流报错“没有适用于此应用程序的地址”
    SharePoint 2016 工作流报错“未安装应用程序管理共享服务代理”
    SharePoint JavaScript API in application pages
    SharePoint 2016 每天预热脚本介绍
    SharePoint 无法删除搜索服务应用程序
  • 原文地址:https://www.cnblogs.com/flyingrun/p/13428168.html
Copyright © 2011-2022 走看看