二分查找
来源:互联网 发布:怎样看出淘宝是包邮的 编辑:程序博客网 时间:2024/06/03 17:28
二分查找问题,找到后返回所在索引,否则返回-1。有以下几种情况:
1. 有序、无重复数组的查找
int binSearch(int *arr, int n, int key) { int low = 0, high = n - 1; while (low < high) { int mid = low + (-low + high) / 2; if (arr[mid] == key) { return mid; } else if(arr[mid] < key) { low = mid + 1; } else high = mid - 1; } return -1;}
2. 有序、有重复数组的查找
可能需要返回首次、末次出现的位置。这时候循环条件要做一下改变。循环条件需要满足,查找范围在缩小(丢掉的数字至少为1个)
2.1 返回最后一次出现的位置
对于arr[mid]>key,array[mid...high]均小于key,x只可能存在于arr[low...mid-1]中。数组减少的长度为high-mid+1,至少为1。
对于arr[mid]==key, arr[mid]是array[left, ..., mid]中最后一个值为key的元素,那么只能在arr[mid, ... ,right]中找,数组减少长度为mid-left。想要保证查找范围在减少,需要保证mid-left>0 !又因为mid = low + (-low + high) / 2 得high - low > 1,即满足这个条件才可以循环!
对于arr[mid]<key, arr[low...mid]均小于key,x只可能在[mid+1...high]之中。数组减少的长度为(mid-low)+1,至少为1。
最后返回high的值
int binSearch_last(int *arr, int n, int key) { int low = 0, high = n - 1; while (low + 1 < high) { int mid = low + (-low + high) / 2; if (arr[mid] > key) high = mid - 1; else low = mid; } if (arr[high] == key) return high; return -1;}
2.2 返回第一次出现的位置
对于arr[mid]<key,array[left, ..., mid]均小于key,x只可能存在于arr[mid+1, ..., high]中。数组减少的长度为mid-left+1,至少为1。
对于arr[mid]==key, arr[mid]是array[left, ..., mid]中最后一个值为key的元素,那么只能在arr[mid, ... ,high]中找,数组减少长度为mid-left。想要保证查找范围在减少,需要保证mid-left>0 !又因为mid = low + (-low + high) / 2 得high - low > 1,即满足这个条件才可以循环!
对于arr[mid]>key, arr[mid, ..., right]均大于key,x只可能在[left, ..., mid-1]之中。数组减少的长度为(right-mid)+1,至少为1。
最后返回low的值
int binSearch_first(int *arr, int n, int key) { int low = 0, high = n - 1; while (low + 1 < high) { int mid = low + (-low + high) / 2; if (arr[mid] < key) low = mid + 1; else high = mid; } if (arr[low] == key) return low; return -1;}
3. 练习题
《剑指offer》 中的旋转数组的最小数字
class Solution {public: int findLiner(int *arr, int left, int right) { int min_val = arr[left]; for (int i = left + 1; i <= right; i++) { if (min_val > arr[i]) min_val = arr[i]; } return min_val; } int rotateNum(int *arr, int n) { int left = 0, right = n - 1, mid = 0; while (left + 1 < right) { mid = left + ((right - left) >> 1); if (arr[mid] > arr[left]) { left = mid; } else if (arr[mid] == arr[left] && arr[mid] == arr[right]){ return findLiner(arr, left, right); } else right = mid; } return arr[mid]; }};
leetcode Split Array Largest Sum
class Solution {public: int splitArray(vector<int>& nums, int m) { long long left = 0, right = 0; for (int i = 0; i < nums.size(); ++i) { left = max((int)left, nums[i]); right += nums[i]; } while (left < right) { long long mid = left + (right - left) / 2; if (can_split(nums, m, mid)) right = mid; else left = mid + 1; } return left; } bool can_split(vector<int>& nums, int m, int sum) { int cnt = 1, curSum = 0; for (int i = 0; i < nums.size(); ++i) { curSum += nums[i]; if (curSum > sum) { curSum = nums[i]; ++cnt; if (cnt > m) return false; } } return true; }};
0 0
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- c#中的关键字out是什么意思?ref是什么意思?它们有什么区别?
- 使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案
- Scala语言扫盲第四篇:类与对象
- JavaScript函数绑定
- Redis数据类型之String类型
- 二分查找
- Cocos2d-过渡篇(三) 触摸机制
- 爬取糗事百科文字段子,(2016年10月22日可用)
- 欢迎使用CSDN-markdown编辑器
- dfs找环
- 欢迎加入我们的iOS开发交流群
- 编辑距离(动态规划法)
- ionic-app.js分析
- 笔记:TRULY_SPINACH(优酷播单:3D坦克大战实例)