算法與數據結構基礎 - 折半查找(Binary Search)


Binary Search基礎

應用於已排序的數據查找其中特定值,是折半查找最常的應用場景。相比線性查找(Linear Search),其時間復雜度減少到O(lgn)。算法基本框架如下:

   //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內用的查找方法即是折半查找。

相關LeetCode題:

704. Binary Search  題解

34. Find First and Last Position of Element in Sorted Array  題解

33. Search in Rotated Sorted Array  題解

 

按值范圍折半查找

折半查找還可以應用於非有序區間查找滿足特定條件的值。該場景下所找的值 在已知范圍內,這時折半的不是索引,而是 值本身所在的范圍。算法基本框架如下:
    //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  題解 

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 的位置,最終最長的序列長度即為所求。詳細算法過程說明見 這里 這里


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM