数组翻转系列
来源:互联网 发布:大腿内侧黑色素知乎 编辑:程序博客网 时间:2024/06/16 20:15
数组翻转后形成的数组,如何在这个数组中查找某个数?如何查找最小值?
查找有序数组当然是二分数组最快了。但是现在这个有序数组经过了翻转,形成了两端有序数组。怎么办?
最好的思想,是把图画出来,再进行分析:
原始数组是一个递增(或非递减)数组,翻转数组则如右图所示。我们可以利用 nums[end] 作为切分参考点,判断每一次mid落在哪一段,然后再通过target和nums[mid], nums[start], nums[end]的关系,判断target是不是落在一段连续的有序区间,再决定下一次搜索向左还是向右。
在不断缩小搜索范围的时候,我们是有可能得到一段连续的有序数组的,很幸运的,按上面的思路写的代码,也能满足只有一段连续区间的情况。
问题1.1:在无重复的翻转数组中查找某个数,返回下标,or - 1。
int search(vector<int>& nums, int target) { int start = 0; int end = nums.size() - 1; while (start <= end) { int mid = start + ((end - start) >> 1); if (nums[mid] == target) { return mid; //查找到了,返回index } if (nums[mid] > nums[end]) { //mid在第一段 if (target < nums[mid] && target >= nums[start]) { //target在最左一段连续区间 end = mid - 1; //向左边缩小范围查找 } else { start = mid + 1; //向右边缩小范围查找 } } else { //mid在第二段 if (target > nums[mid] && target <= nums[end]) { //target在最右一段连续区间 start = mid + 1; //向右边缩小范围查找 } else { end = mid - 1; //向左边缩小范围查找 } } } return -1; }
问题1.2:在有重复的翻转数组中查找否个数,存在则返回true,反之false。
相比如无重复的翻转数组,有重复的情况要复杂一点,就是当 nums[mid] == 分界点 nums[end] 时,无法判断他是落在第一段还是第二段,但是我们知道
nums[mid] != target,则此时nums[end] !=target,那我们让 end--,直到这个分界点是一个开的点,而不是闭的点。之后的步骤和问题1.1一样。
bool search(vector<int>& nums, int target) { int start = 0; int end = nums.size() - 1; while (start <= end) { int mid = start + ((end - start) >> 1); if (nums[mid] == target) { return true; } if (nums[mid] > nums[end]) { if (target < nums[mid] && target >= nums[start]) { end = mid - 1; } else { start = mid + 1; } } else if (nums[mid] < nums[end]) { if (target > nums[mid] && target <= nums[end]) { start = mid + 1; } else { end = mid - 1; } } else { end--; } } return false; }
问题2.1:在无重复的翻转数组中查找最小值。
当nums[mid] > nums[end] 说明mid落在第一段,最小值肯定在第二段。所以start = mid + 1。否则mid落在第二段,此时mid落在的点,也可能是最小值,所以end = mid。又因为我们在求mid的时候是向下取整,所以可以保证收敛。而收敛点即是最小点。
int findMin(vector<int>& nums) { int start = 0; int end = nums.size() - 1; while (start < end) { int mid = start + ((end - start) >> 1); if (nums[mid] > nums[end]) { start = mid + 1; } else { end = mid; } } return nums[start]; }
问题2.2 : 在有重复的翻转数组中查找最小值。
这个也是个有重复的翻转数组问题,考虑和问题1.2一样,在 nums[mid] == nums[end] 的时候,我们无法判断 mid落在哪一段,但是可以确定,nums[end] 是 <= 最小值的,这时候可以让 end--。也可以收敛到最终结果。
int findMin(vector<int>& nums) { int start = 0; int end = nums.size() - 1; while (start < end) { int mid = start + ((end - start) >> 1); if (nums[mid] > nums[end]) { start = mid + 1; } else if (nums[mid] < nums[end]) { end = mid; } else { end--; } } return nums[start]; }
- 数组翻转系列
- 数组翻转
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 翻转数组
- 数组翻转
- 翻转数组
- 翻转数组
- 数组翻转
- 编程 错误处理和调试技巧
- SpringMVC+Mybatis+log4g打印sqlyu
- PHP技术讨论群
- CentOS下安装JDK的三种方法
- amlogic android 7.0 修改系统分区大小
- 数组翻转系列
- UVA 10474
- vue中的滚动监听
- 解决国内NPM安装依赖速度慢问题
- spring学习笔记八 bean生命周期
- java 文件下载
- Git学习——如何进入到某个本地git库
- 原生JS实现AJAX、JSONP及DOM加载完成事件,并提供对应方法
- UVA 639