二分搜索总结

BinarySearch题目汇总:

LintCode - Binary Search

 

  • temp笔记?:

二分搜索题暂时分两种情况:

case1:找到了就OK——while循环中要写return,如果跳出循环,说明一定没找到;

case2:必须“遍历”完整个数组才能得出结果——while循环中没有return,循环结束,给出结果(找到/没找到都可能)

一 普通二分搜索

LintCode 457. Classical BInary Search

public class Solution {
    /**
     * @param nums: An integer array sorted in ascending order
     * @param target: An integer
     * @return: An integer
     */
    public int findPosition(int[] nums, int target) {
        
        int lo = 0, hi = nums.length-1;
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(nums[mid] == target)     //如果找到了,则返回
                return mid;             
            if(nums[mid] > target)
                hi = mid - 1;
            else
                lo = mid + 1;
        }
        return -1;   //跳出循环,一定没找到
    }
}

二 查找满足条件的第一个位置

LintCode 14. First Position of Target

public class Solution {
    /**
     * @param nums: The integer array.
     * @param target: Target to find.
     * @return: The first position of target. Position starts from 0.
     */
    public int binarySearch(int[] nums, int target) {
        // write your code here
        int lo = 0, hi = nums.length-1;
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(nums[mid] >= target)   //注:此处条件设置成nums[i]>=target而不是==target
                hi = mid - 1;
            else
                lo = mid + 1;
        }
        return nums[lo] == target ? lo : -1; //while循环结束后,nums[lo]是第一个>=target的数,再判断它是否满足条件
    }
}

相似题目a:

LintCode 74. First Bad Version

LeetCode 278. First Bad Version

    public int findFirstBadVersion(int n) {
        // write your code here
        int lo = 1, hi = n;
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(SVNRepo.isBadVersion(mid))
                hi = mid - 1;
            else
                lo = mid + 1;
        }
        return lo;
    }

相似题目b:

LintCode 60. Search Insert Position

LeetCode 35. 搜索插入位置  

class Solution {
    public int searchInsert(int[] nums, int target) {
        //如果找到target,立刻返回其位置;
        //否则,寻找数组中第一个大于target的元素的位置,就是target的插入位置
        int lo = 0, hi = nums.length-1;
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(nums[mid] == target)
                return mid;
            if(nums[mid] > target)
                hi = mid - 1;
            else
                lo = mid + 1;
        }
        return lo;
    }
}

三 查找满足条件的最后一个位置

tip:也可以改为“查找不满足条件的第一个位置”,则和二 查找满足条件的第一个位置相同思路。

LintCode 458. Last Position of Target

    public int lastPosition(int[] nums, int target) {
        // write your code here
        int lo = 0, hi = nums.length-1;
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(nums[mid]<=target)
                lo = mid + 1;
            else
                hi = mid - 1;
        }
        //此时,hi是满足条件nums[i]<=target的最后一个位置,取值可能为-1和0,1,...,n-1.
        if(hi < 0) return -1; //hi = -1说明所有元素均大于target
        return nums[hi] == target ? hi : -1; //nums[hi]是<=target的最后一个元素,要判断是否==target
    }

相似题目:

LintCode 141. Sqrt(x)

LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] ans = {-1,-1};
        
        //查找nums[i]>=target的第一个位置:
        int lo = 0, hi = nums.length-1;
        if(hi < 0) return ans;
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(nums[mid] >= target) 
                hi = mid - 1;
            else
                lo = mid + 1;
        }
        //此时 nums[lo]为>=target的第一个位置,但不保证==target
        if(lo == nums.length || nums[lo] != target) return ans; //target不存在
        ans[0] = lo; //否则 target一定存在
        
        //查找nums[i] <= target的最后一个位置:
        hi = nums.length-1; //此时lo指向target出现的第一个位置,不用动
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(nums[mid] <= target)
                lo = mid + 1;
            else
                hi = mid - 1;
        }
        //此时 nums[hi]为<=target的最后一个位置,且已知target一定存在
        ans[1] = hi;
        return ans;
    }
}

四 变形题目

LintCode 75. Find Peak Element 寻找峰值

public class Solution {
    /**
     * @param A: An integers array.
     * @return: return any of peek positions.
     */
    public int findPeak(int[] A) {
        // write your code here
        int lo = 1, hi = A.length-2; //【注意:mid不能取到数组的第一个或是最后一个元素】
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(A[mid-1] < A[mid] && A[mid] > A[mid+1])
                return mid;
            if(A[mid-1] < A[mid])
                lo = mid + 1;
            else
                hi = mid - 1;
        }
        return -1; //一定有峰值,所以永远不会执行这一句。
    }
}

力扣 162. 寻找峰值

与LintCode不同在于,需要先判断第一个/最后一个元素是否为峰值。

class Solution {
    public int findPeakElement(int[] nums) {
        int len = nums.length;
        if(len == 1 || nums[0] > nums[1]) return 0; //第一个元素是否是峰值
        if(nums[len-1] > nums[len-2]) return len-1; //最后一个元素是否是峰值
        
        int lo = 1, hi = nums.length-2;
        while(lo <= hi) {
            int mid = lo + (hi-lo)/2;
            if(nums[mid] > nums[mid-1] && nums[mid] > nums[mid+1])
                return mid;
            if(nums[mid] > nums[mid-1]) lo = mid + 1;
            else hi = mid - 1;
        }
        return -1;
    }
}

 

五 temp总结

 

5.1 二分法:寻找满足条件的第一个元素

写法1:

while循环结束后,lo代表满足条件的第一个元素的位置。假设nums = [ 0,1,2,3,4 ],长度为5。此时,lo的取值有两种可能——

第一种情况,lo = 5,超出nums索引范围,代表nums中没有满足条件的元素。

第二种情况,lo取值在0~4之间,代表满足条件的第一个元素位置为lo。

int lo = 0, hi = nums.length-1;
while(lo <= hi) {
    int mid = lo + (hi-lo) / 2;
    if(nums[mid] 满足条件)
        hi = mid - 1;
    else
        lo = mid + 1;
}
if(lo == nums.length) return -1; //没有满足条件的元素
return nums[lo];                 //满足条件的第一个位置为lo

写法2:

int lo = 0, hi = nums.length - 1;
while(lo < hi) {
    int mid = lo + (hi - lo) / 2;
    if(nums[mid] 满足条件)
        hi = mid;
    else
        lo = mid + 1;
}
return nums[lo]; //或者 nums[hi],因为此时lo = hi

5.2 二分法:寻找满足条件的最后一个元素

写法1:

while循环结束后,hi代表满足条件的最后一个元素的位置。假设nums = [ 0,1,2,3,4 ],长度为5。此时,hi的取值有两种可能——

第一种情况,hi = -1,超出nums索引范围,代表nums中没有满足条件的元素。

第二种情况,hi取值在0~4之间,代表满足条件的最后一个元素位置为hi。

int lo = 0, hi = nums.length-1;
while(lo <= hi) {
    int mid = lo + (hi-lo)/2;
    if(nums[mid]满足条件)
        lo = mid + 1;
    else
        hi = mid - 1;
}
if(hi == 0) return -1;
return nums[hi];

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值