来源:链接:https://www.nowcoder.com/practice/7bc4a1c7c371425d9faa9d1b511fe193?tpId=188&&tqId=36844&rp=1&ru=/activity/oj&qru=/ta/job-code-high-week/question-ranking
声明:如果我侵犯了任何人的权利,请联系我,我会删除
欢迎高手来喷我
文章目录
题目描述 请实现有重复数字的有序数组的二分查找。
输出在数组中第一个大于等于查找值的位置,如果数组中不存在这样的数,则输出数组长度加一。
示例1
输入 5,4,[1,2,4,4,5]
返回值 3
输出位置从1开始计算
代码,二分细节是魔鬼
import java.util.*;
public class Solution {
/**
* 二分查找
* @param n int整型 数组长度
* @param v int整型 查找值
* @param a int整型一维数组 有序数组
* @return int整型
*/
public int upper_bound_ (int n, int v, int[] a) {
//数组是排序好的, 那么判断最后一个值大于查找值,那么没有查找的意义了
if(a[n-1] < v) return n+1;
int left = 0, right = a.length;
while(left < right){
int mid = left + (right - left)/2;
if(a[mid] > v) right = mid;
else if(a[mid] < v) left = mid+1;
//这里是应对重复值得思路
//重复值,就顺序查找
else{ //a[mid] == v
while(mid >=0 && a[mid]==v) mid--;
//为什么是+2???因为此时mid指向小于v的最后一个值,
//mid+1指向等于v的第一个值,mid+1+1才是 符合“输出位置从1开始计算 ”的结果
return mid+2;
}
}
//输出位置从1开始计算 所以加1
return left + 1;
}
}
题目描述 转动过的有序数组寻找目标值
给出一个转动过的有序数组,你事先不知道该数组转动了多少
(例如,0 1 2 4 5 6 7可能变为4 5 6 7 0 1 2).
在数组中搜索给出的目标值,如果能在数组中找到,返回它的索引,否则返回-1。
假设数组中不存在重复项。
示例1
输入 [1],0
返回值 -1
示例2
输入 [3,2,1],1
返回值 2
代码 分情况:1 Arr[mid]=target 2:右半部有序 3:左半部有序
对旋转数组进行均等划分后,总有一边是有序的,如:
10 11 12 13 14 15 1 2 3
10 11 15 1 2 3 4 5 6 7 8
我们定位到有序的一边后,对比target与有序子数组的左右边界,就可以作出搜索左侧还是右侧的决策。
import java.util.*;
public class Solution {
/**
*
* @param A int整型一维数组
* @param target int整型
* @return int整型
*/
public int search (int[] A, int target) {
// write code here
int left = 0, right = A.length-1;
while(left <= right){
int mid = left + (right-left)/2;
if(A[mid] == target) return mid;
else if(A[mid] < A[right]){ //右半部有序
if(A[mid] < target && target <= A[right]) left = mid+1;
else right = mid - 1;
}else{ //左半部有序
if(target < A[mid] && A[left]<= target) right = mid-1;
else left = mid + 1;
}
}
//不要想太多,找不到就返回-1
return -1;
}
}
题目描述 剑指 Offer 11. 旋转数组的最小数字
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
示例 2:
输入:[2,2,2,0,1]
输出:0
代码 细节的二分
我们考虑数组中的最后一个元素 x:在最小值右侧的元素,它们的值一定都小于等于 x;
而在最小值左侧的元素,它们的值一定都大于等于 x。因此,我们可以根据这一条性质,通过二分查找的方法找出最小值。
- 第一种情况是 numbers[pivot]<numbers[high]。这说明 numbers[pivot] 是最小值右侧的元素,因此我们可以忽略二分查找区间的右半部分。
- 第二种情况是 numbers[pivot]>numbers[high]。 这说明 numbers[pivot] 是最小值左侧的元素,因此我们可以忽略二分查找区间的左半部分。
- 第三种情况是 numbers[pivot]==numbers[high]。由于重复元素的存在,我们并不能确定 numbers[pivot] 究竟在最小值的左侧还是右侧,
class Solution {
public int minArray(int[] numbers) {
int left = 0, right = numbers.length-1;
while(left <= right){
int mid = left + (right - left)/2;
if(numbers[mid] < numbers[right]){
//这里为什么不是right-1??因为mid这个值是小值,可能是我的所求,所以到带入下一次比较
right = mid;
}else if(numbers[mid] > numbers[right]){
left = mid+1;
}else{
right--;
}
}
return numbers[left];
}
}
大神总结的二分,各种细节各种应用
详解二分查找算法https://www.cnblogs.com/kyoner/p/11080078.html