所用算法:二分搜索
一维:
算法说明:二分搜索从有序序列中寻找某个给定的值
算法思想:二分法首先从中心位置开始搜索,如果中心位置的元素正好是要找的元素,搜索完成;如果不是,假如中心位置的元素小于要找的元素,则从序列的后半部分找,如果中心位置的元素大于要找的元素则从中心位置的前半部分找。在缩小的范围中再重新确定一个中心位置重复之前的过程。
需要注意的几个问题:
(1)如果一开始时左闭右闭的话(也就是左边和右边都没有超出索引范围,左边起始值是0,右边起始值是size-1),中间过程也应该是左闭右闭的(也就是左边的值和右边的值无论何时都不会包含上一个中间值)
如果一开始时左闭右开的话(也就是左边没有超出索引范围,而右边超出了,左边起始值是0,右边起始值是size),中间过程也应该是左闭右开的(也就是左边的值无论合适都不会包含上一个的中间值,而和右边的值始终都包含上一个的中间值)
(2)到底是小于等于还是小于,这要看是否有意义,当左闭右开的话,右边的值可以等于左边的值,那么小于等于中的等于就有意义,此时应该写小于等于;如果是左闭右开的话,右区间永远不可能等于左区间那么等于就没有意义,那么应该是小于。
1 int search(vector<int>& nums, int target) { 2 using vec_index=decltype(nums.size()); 3 vec_index begin=0,end=nums.size(); 4 while(begin<end){ 5 vec_index mid=begin+((end-begin)>>1); 6 if(target==nums[mid]) 7 return mid; 8 else if(target>nums[mid]) 9 begin=mid+1; 10 else 11 end=mid; 12 } 13 return -1; 14 }
该程序实现:如果没有查找到目标元素就返回-1,否则返回元素所在下标。
二维:
剑指 Offer 04. 二维数组中的查找 - 力扣(LeetCode)
算法思想:从第一行最后一列开始搜索,如果待查找的数比它大则列数不变,行数加一,如果待查找的数比它小则行数不变列数减一。
1 bool Find(int target, vector<vector<int> > array) 2 { 3 if(array.empty()||array[0].empty()) return false; 4 int row=0,col=array[0].size()-1,array_size=array.size(); 5 while (row<array_size&&col>=0) 6 { 7 if(target<array[row][col]) --col; 8 else if(target>array[row][col]) ++row; 9 else return true; 10 } 11 return false; 12 }
该程序实现在矩阵中查找目标元素,如果查找到则返回true否则返回false。
但是本人又对上面的算法进行改进,即先从最后一列最中间的那个数和待查找的数进行比较,如果待查找的数比中间的那个大,则从中间那行的下一行最后一列的那个元素开始搜索,如果待查找的数比它大则列数不变,行数加一,如果待查找的数比它小则行数不变列数减一。
1 bool Find(int target, vector<vector<int> > array) { 2 if(array.empty()||array[0].empty()) return false; 3 int row=array.size()/2+1,col=array[0].size()-1,array_size=array.size(); 4 if(target==array[row-1][col]) return true; 5 else if(target<array[row-1][col]) row=0; 6 7 while (row<array_size&&col>=0) 8 { 9 if(target<array[row][col]) --col; 10 else if(target>array[row][col]) ++row; 11 else return true; 12 } 13 return false; 14 } 15 };
这种算法如果一开始待查找的数比中间那个大,则会极大的节省时间。