# Binary search ###### tags: `Study_aboard` ## Binary search algorithm https://www.cnblogs.com/grandyang/p/6854825.html Timing : To search a sorted array Complexity : $log{_2}{N}$ Specify left, right, mid, compare mid with the target and change right or left continuously (夾擊法) ![](https://i.imgur.com/O1vWxH6.png) ### 1. Find Exactly The Target ==Watch out and remeber left < right, left = mid+1, right = mid== Explain: If left=right=mid, right will = mid = itself and will generate loop forever ```cpp int find(vector<int>& nums, int target) { int left = 0, right = nums.size(); while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid + 1; else right = mid; } return -1; } ``` ### 2. Find the first number that is greater or equal to the target ```cpp // !!! the only difference between 1 and 2 is that it do not return when nums[mid]==target int find(vector<int>& nums, int target) { int left = 0, right = nums.size(); while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < target) left = mid + 1; else right = mid; } return right; } ``` right-1 is also the larget element that is smaller than the target ### 3. Find the smallest elements that is greater than the target ```cpp // the difference between 2 and 3 is that when it is equal, 2 will move right to mid, 3 will move left to mid int find(vector<int>& nums, int target) { int left = 0, right = nums.size(); while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] <= target) left = mid + 1; else right = mid; } return right; } ``` ## Search in Rotated Sorted Array ![](https://i.imgur.com/q2s9UcC.png) ![](https://i.imgur.com/o4jhL8z.png) Initial: 找到變更點,比較與target間的大小後,對區間進行binary search Problem: 找到變更點 time complexity = O(n) Sol: 不找變更點,而是在binary search 中判斷區間為ascending or descending,下圖為0,1,2,3,4,5,6,7 所有rotate的可能 ![](https://i.imgur.com/QnchTqb.png) ==找到規律,若mid<right,則mid~right為ascending orders, 若mid<right,則左半邊為ascending orders== ```cpp class Solution { public: int search(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; if (nums[mid] < nums[right]) { // ascending if (nums[mid] < target && nums[right] >= target) left = mid + 1; // if nums[mid]<target<nums[right] else right = mid - 1; // if target<nums[mid] || target>nums[right] // notice : when target>nums[right], means that the rotated part is in 0~mid, thus right=mid-1 } else { // means left to mid is ascending if (nums[left] <= target && nums[mid] > target) right = mid - 1; else left = mid + 1; } } return -1; } }; ``` ## Search in Rotated Sorted Array II ![](https://i.imgur.com/PcfRcky.png) ![](https://i.imgur.com/lqrZT39.png) ==Hard to me== Initial: Problem: duplicate may cause error when mid=right ex: 1111112111, we do not know which side we should sort Sol: when mid=right, right-=1, and run the loop again until they are not equal ```cpp class Solution { public: bool search(vector<int>& nums, int target) { int n = nums.size(), left = 0, right = n - 1; while (left <= right) { int mid = (left + right) / 2; if (nums[mid] == target) return true; if (nums[mid] < nums[right]) { if (nums[mid] < target && nums[right] >= target) left = mid + 1; else right = mid - 1; } else if (nums[mid] > nums[right]){ if (nums[left] <= target && nums[mid] > target) right = mid - 1; else left = mid + 1; } else --right; } return false; } }; ``` ## Find First and Last Position of Element in Sorted Array ![](https://i.imgur.com/wclcHh9.png) ![](https://i.imgur.com/3LW8hDT.png) Find the first greater or equal position - binary search type II ```cpp class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { int left=0, right=nums.size()-1, mid; vector <int> res; if(nums.size()==0){ res.push_back(-1); res.push_back(-1); return res; } while(left<right){ mid = left + (right-left)/2; if(nums[mid]<target) left=mid+1; else right=mid; } if(nums[right]!=target){ res.push_back(-1); res.push_back(-1); return res; } res.push_back(right); for(int i=right+1;i<nums.size();i++){ if(nums[i]==target) right++; else break; } res.push_back(right); return res; } }; ``` ## Longest Increasing Subsequence ==Important== ![](https://i.imgur.com/ZoFscJU.png) 2. Method 2 : Combine with Binary search DP + Greedy + Binary Search tree [solution by geeksforgeeks](https://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/) ![](https://i.imgur.com/2GVAixz.png) ## Count of Smaller Numbers After Self ![](https://i.imgur.com/YBBKJGa.png) ![](https://i.imgur.com/06Ne1yj.png) Initial: want to sort the array first and then binary search for the lowest bound of the target Problem: TLE Solution: No solution yet ```cpp class Solution { public: vector<int> countSmaller(vector<int>& nums) { vector<int> res,sorted_nums = nums; sort(sorted_nums.begin(),sorted_nums.end()); for(int i=0;i<nums.size();i++){ int target = nums[i]; // binary search type II int left=0, right=sorted_nums.size()-1; while(left<right){ int mid = left+ (right-left)/2; if(sorted_nums[mid]<target) left=mid+1; else right=mid; } // There are 2 situations // 1. no other is bigger than the target -> return right // 2. there is some number bigger than the target -> return rigjt-1 if(sorted_nums[right]==target){ res.push_back(right); sorted_nums.erase(sorted_nums.begin()+right); } else{ res.push_back(right-1); sorted_nums.erase(sorted_nums.begin()+right-1); // erase the target } } return res; } }; ``` revised version: ==不用先sort整串數列==,而是由==最後一位數開始==(最後一位的右方為空,因此可以作為新數列的第一位)binary search的插入新數列。而其所在的位置即為小於的數字個數。 ```cpp // Binary Search class Solution { public: vector<int> countSmaller(vector<int>& nums) { vector<int> t, res(nums.size()); for (int i = nums.size() - 1; i >= 0; --i) { int left = 0, right = t.size(); while (left < right) { int mid = left + (right - left) / 2; if (t[mid] >= nums[i]) right = mid; else left = mid + 1; } res[i] = right; t.insert(t.begin() + right, nums[i]); } return res; } }; ```