目录
力扣852.山脉数组的峰顶索引
力扣162.寻找峰值
力扣153.寻找旋转排序数组中的最小值
力扣剑指Offer53.0-n-1缺失的数字
力扣852.山脉数组的峰顶索引
峰顶之前的全部比他小,峰顶之后的也比他小,把小于等于和大于分成两段
class Solution {
public int peakIndexInMountainArray(int[] arr) {
//第一个和最后一个都不是峰值
int left=1;
int right=arr.length-2;
while(left<right){
int med=left+(right-left+1)/2;
if(arr[med]>arr[med-1]){
left=med;
}else{
right=med-1;
}
}
return left;
}
}
力扣162.寻找峰值
暴力解法,从第一个位置开始,一直向后面走,然后分类讨论即可。
这种没有顺序的,我们该如何使用二分呢?
二段性
峰值一定一个在左边,另一个一定在右边
代码怎么写,怎么规定是我们决定的,你的思想决定你的想法。
这里我其实一直区分不出来什么时候是+1,-1什么时候是正好=med,我的想法是,你看你需要什么,这道题是要求峰值,峰值一定是最大的那个是数字,那么假如代码里面x>m
你肯定是要保留这个x,那么你就让right/left=x,因为你是要保留大的,反之也一样
class Solution { public int findPeakElement(int[] nums) { int left=0; int right=nums.length-1; while(left<right){ int med=left+(right-left)/2; if(nums[med]>nums[med+1]){ right=med; }else{ left=med+1; }} return left; } }
方法2:(一样的思想,只不过操作不同,但是大同小异罢了)
class Solution { public static int findPeakElement(int[] nums) { int left=0; int right=nums.length-1; while(left<right){ int med=left+(right-left+1)/2; if(nums[med]>nums[med-1]){ left=med; }else{ right=med-1; }} return left; } }
力扣153.寻找旋转排序数组中的最小值
以D为参照点,如果说我的nums[n-1]是这个D点,那么比D点大的,就一定要往右边去(因为右边较小),比D小的就一定往左边来。(假如D是最大的,那么他就会一直往左边走,也是符合理想的)
那我我们想一想,假如说是以A为参照点,我们该怎么办呢?,nums[mid]比A大,那么就是right放在mid的右边,假如比A小那么left去找mid的右边
以D为参照点,推荐是以D为参照点处理,推荐,以D为参照点,划分的更加明确,是比D大,和比D小两个阶段,比D大,就可以直接往左边移动到比D小的,比D小,可以往左移动看有没有比D更小的。
class Solution {
public int findMin(int[] nums) {
int left=0;
int right=nums.length-1;
int x=nums[nums.length-1];
for(int i=0;i<nums.length;i++){
int mid=left+(right-left)/2;
if(nums[mid]>x){
left=mid+1;
}else{
right=mid;
}
}
return nums[left];
}
}
一样的原理,但是有特殊情况
以A为参照点处理。
两点细节,比D点为参照点多两个条件
public static int findMin(int[] nums) {
int left=0;
int right=nums.length-1;
int x=nums[0];
if(nums.length==1){return nums[0];}
if(nums[0]<nums[right]){
return nums[0];
}
for(int i=0;i<nums.length;i++){
int mid=left+(right-left)/2;
if(nums[mid]>=x){
left=mid+1;
}else{
right=mid;
}
}
return nums[left];
}
力扣剑指Offer53.0-n-1缺失的数字
直接拿事例理解
[0,1,3]缺少一个2
[0,1,2,3,4,5,6,7,9]缺少一个8