算法与数据结构基础 - 折半查找(Binary Search)

Binary Search基础css

应用于已排序的数据查找其中特定值,是折半查找最常的应用场景。相比线性查找(Linear Search),其时间复杂度减小到O(lgn)。算法基本框架以下:html

   //704. Binary Search
int search(vector<int>& nums, int target) { //nums为已排序数组 int i=0,j=nums.size()-1; while(i<=j){ int mid=(i+j)/2; if(nums[mid]==target) return mid; else if(nums[mid]>target) j=mid-1; else i=mid+1; } return -1; }

以上查找范围的上下限 i 和 j 表明索引,算法过程可视化:Binary Search,STL中有序区间函数upper_bound/lower_bound内用的查找方法便是折半查找。git

相关LeetCode题:github

704. Binary Search  题解算法

34. Find First and Last Position of Element in Sorted Array  题解数组

33. Search in Rotated Sorted Array  题解框架

 

按值范围折半查找dom

折半查找还能够应用于非有序区间查找知足特定条件的值。该场景下所找的值 在已知范围内,这时折半的不是索引,而是 值自己所在的范围。算法基本框架以下:
    //287. Find the Duplicate Number
int
findDuplicate(vector<int>& nums) { int n=nums.size(); int i=1,j=n-1; //[i,j]表示值的区间 while(i<=j){ int mid=(i+j)/2,count=0; for(auto k:nums) if(k<=mid) ++count; //根据计数折半缩小区间if(count<=mid) i=mid+1; else j=mid-1; } return i; //最终返回值自己 }

相关LeetCode题:函数

378. Kth Smallest Element in a Sorted Matrix  题解 spa

875. Koko Eating Bananas  题解

1011. Capacity To Ship Packages Within D Days  题解

410. Split Array Largest Sum   题解

 

折半查找求递增序列

求递增序列(LIS, longest increasing subsequence)是一道经典的算法题目,用折半查找对其进行求解的方法十分巧妙,求解代码以下:

    //300. Longest Increasing Subsequence
int lengthOfLIS(vector<int>& nums) { int size=0; vector<int> tail(nums.size()); //候选递增序列集for(auto num:nums){ int i=0,j=size; while(i<j){ int mid=(i+j)/2; if(tail[mid]<num) i=mid+1; else j=mid; } tail[i]=num; if(i==size) size++; } return size; }

以上设定LIS候选序列集 tail,对无序区间 nums 中的各个值经过折半查找的方法,找到其落在 tail 的位置,最终最长的序列长度即为所求。详细算法过程说明见 这里 这里

相关文章
相关标签/搜索