【笔记】二分法的各种变形和例题

一、总览

在这里插入图片描述

二、完全有序的二分查找

2.1 原始二分查找

https://leetcode-cn.com/problems/search-insert-position/

解题:这道题是最原始的二分查找,时间复杂度O(logn) ,注意边界条件:low <= high

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) 
    {
        int low = 0, high = nums.size() - 1;
        while (low <= high)
        {
            int mid = low + (high - low) / 2;
            if (nums[mid] == target)
                return mid;
            else if (nums[mid] < target)
                low = mid + 1;
            else
                high = mid - 1;
        }
        return low;
    }
};

2.2 寻找第一个等于元素的位置

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

解题:这个题可用原始二分查找,只需要加上判断是不是第一个位置的条件,如果不是则high = mid - 1

class Solution {
public:
    int searchFirst(vector<int>& nums, int target) 
    {
        int low = 0, high = nums.size() - 1;
        while (low <= high)
        {
            int mid = low + (high - low) / 2;
            if (nums[mid] == target)
            {
            	if(mid == 0 || nums[mid - 1] != target)
            		return mid;
            	high = mid - 1;
            }
            else if (nums[mid] < target)
                low = mid + 1;
            else
                high = mid - 1;
        }
        return -1;
    }
};

2.3 寻找最后一个等于元素的位置

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

解题:和找第一个相等位置相同,只要改下判断nums[mid] == target时的逻辑

class Solution {
public:
    int searchLast(vector<int>& nums, int target) 
    {
        int low = 0, high = nums.size() - 1;
        while (low <= high)
        {
            int mid = low + (high - low) / 2;
            if (nums[mid] == target)
            {
            	if(mid == nums.size() || nums[mid + 1] != target)
            		return mid;
            	low = mid + 1;
            }
            else if (nums[mid] < target)
                low = mid + 1;
            else
                high = mid - 1;
        }
        return -1;
    }
};

2.4 寻找第一个大于元素的位置

class Solution {
public:
	int BinSearch(vector<int>& nums, int target)
    {
        int left = 0, right = nums.size() - 1;
        while (left <= right)
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] <= target)
                // 说明第一个大于tar的元素在[mid+1, right]区间
                left = mid + 1;   
            else 
                // [mid, right]区间的元素都比tar大
                right = mid - 1;       
        }
        // 二分查找结束之后,left的元素一定是大于tar的第一个元素
        if (left < nums.size())
        	return left;
        return -1;	// 到这,说明target比数组中的所有数都大
    }
};

2.5 寻找第一个小于元素的位置

class Solution {
public:
    int BinSearch(vector<int>& nums, int target)
    {
        int left = 0, right = nums.size() - 1;
        while (left <= right)
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid + 1;   
            else 
                right = mid - 1;       
        }
        // 二分查找结束之后,right的元素一定是小于tar的第一个元素
        if (right >= 0)
        	return right;
        return -1;	// 到这,说明target比数组中的所有数都小
    }
};

三、不完全有序的二分查找

3.1 搜索旋转排序数组

https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

在这里插入图片描述

class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        // 二分法:找递增的区间
        // 如果[left, mid]区间是递增的,则target需要和nums[left]比较,划分区间
        // 如果[mid + 1, right]区间是递增的,则target需要和nums[right]比较划分区间
        int left = 0, right = nums.size() - 1;
        while (left <= right)   // 这里注意left <= right
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target)
                return mid;
            if (nums[mid] >= nums[left])    // 左边区间是递增的
            {
                if (target >= nums[left] && target < nums[mid])
                    right = mid - 1;
                else 
                    left = mid + 1;
            }
            else                            // 右边区间是递增的
            {
                if (target <= nums[right] && target > nums[mid])
                    left = mid + 1;
                else 
                    right = mid - 1;
            }
        }
        return -1;
    }
};

3.2 搜索旋转排序数组II (元素可能重复)

https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/

class Solution {
public:
    bool search(vector<int>& nums, int target) 
    {
        if (nums.size() == 0)
            return false;
        int low = 0, high = nums.size() - 1;
        while(low <= high)
        {
            int mid = low + (high - low) / 2;
            if(nums[mid] == target)
                return true;
            else if(nums[mid] > nums[low])
            {
                if(nums[low] <= target && target < nums[mid])
                    high = mid - 1;
                else
                    low = mid + 1;
            }
            else if(nums[mid] < nums[high])
            {
                if(nums[mid] < target && target <= nums[high])
                    low = mid + 1;
                else
                    high = mid - 1;
            }
            else
            {
                if(nums[low] == nums[mid])
                    low++;
                if(nums[high] == nums[mid])
                    high--;
            }
        }
        return false;
    }
};

3.3 寻找旋转排序数组中的最小值

https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/

class Solution {
public:
    int findMin(vector<int>& nums) {
        if(nums.empty()) return -1;
        if(nums.size() == 1) return nums[0];
        int p1 = 0, p2 = nums.size() - 1;
        int mid = p1; // 假如旋转了数组的前面0个元素(也就是没有旋转),我们直接返回numbers[p1]
        while(nums[p1] > nums[p2])
        {
            if(p2 - p1 == 1)
            {
                // 循环终止条件:当p2-p1=1时,p2所指元素为最小值
                mid = p2;
                break;
            }
            mid = p1 + (p2 - p1) / 2;
            if(nums[mid] > nums[p1]) p1 = mid;
            else p2 = mid;
        }
        return nums[mid];
    }
};

3.4 寻找旋转排序数组中的最小值II (元素可能重复)

https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/

class Solution {
public:
    int findMin(vector<int>& nums) 
    {
        int low = 0, high = nums.size() - 1;
        while(low < high)
        {
            if(nums[low] < nums[high])
                return nums[low];
            int mid = low + ((high - low) >> 1);
            if(nums[mid] > nums[low])
                low = mid + 1;
            else if(nums[mid] < nums[low])
                high = mid;
            else
                low++;
        }
        return nums[low];
    }
};

四、二维数组

4.1 搜索二维矩阵

https://leetcode-cn.com/problems/search-a-2d-matrix/

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值