LeetCode 常见--二分搜索--问题,Python实现

二分查找

0. 模板
判断左闭右开区间 = [left, mid, right)
def binary_search(left, right):
    while left < right:
        mid = left + (right - l) // 2
        if isResult(mid):  return mid
        if judge(mid):
            right = mid    # next range = [l, m)
        else:
            left = mid + 1    # next range = [m+1, r)
    return left
1. 求开方

LeetCode 69. Sqrt(x) (Easy)

思路:while循环条件为left <= right,一般情况思路很清晰,这里主要主要边界情况。当while退出循环的时候,一定有left > right,以8为例子,此时left为3,right为2,应当返回right。(边界情况,往往是二分查找需要注意的地方)

# Python
class Solution:
    def mySqrt(self, x: int) -> int:
        if x <= 1: return x
        
        left, right = 1, x
        
        while left <= right:
            mid = (left + right) // 2
            if mid ** 2 > x:
                right = mid - 1
            elif mid ** 2 < x:
                left = mid + 1
            else:
                return mid
        return right
    
# C++
class Solution {
public:
    int mySqrt(int x) {
        if (x <= 1) return x;
        long int left = 1, right = x;
        while (left <= right) {
            long int mid = (left + right) / 2;
            if (mid * mid > x)
                right = mid - 1;
            else if (mid * mid < x)
                left = mid + 1;
            else
                return mid;
        }
        return right;
    }
};
2. 大于给定元素的最小元素

LeetCode 744. Find Smallest Letter Greater Than Target (Easy)

方法一:直接比较,时间复杂度 O ( n ) O(n) O(n)

方法二:二分搜索,时间复杂度 O ( log ⁡ n ) O(\log n) O(logn)

# Python
# 方法一
class Solution:
    def nextGreatestLetter(self, letters: List[str], target: str) -> str:
        if letters[-1] <= target: return letters[0]
        
        for item in letters:
            if item > target:
                return item
# 方法二
class Solution:
    def nextGreatestLetter(self, letters: List[str], target: str) -> str:
        if letters[-1] <= target: return letters[0]
        
        left, right = 0, len(letters) - 1
        
        while left <= right:
            mid = (left + right) // 2
            if letters[mid] > target:
                right = mid - 1
            else:
                left = mid + 1
        return letters[left]
    
# C++
class Solution {
public:
    char nextGreatestLetter(vector<char>& letters, char target) {
        if (letters[letters.size()-1] <= target) return letters[0];
        
        int left = 0, right = letters.size() - 1;
        
        while (left <= right) {
            int mid = (left + right) / 2;
            if (letters[mid] > target)
                right = mid - 1;
            else
                left = mid + 1;
        }
        return letters[left];
    }
};
3. 有序数组的Single Element

LeetCode 540. Single Element in a Sorted Array (Medium)

观察案例:

nums:  1 1 2 2 3 3  (4)  5 5 6 6
index: 0 1 2 3 4 5  (6)  7 8 9 10

单独出现的数字为4,4之前成对出现,4之后也成对出现。4之前的数对有index为奇数,对应的是后面的数,index为偶数,对应的是前面的数(一对数的前后)。4之后的数对则刚好相反。利用该条件可以判断,当前数是处于4的前面还是后面。利用此思想进行二分查找。

# Python
class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        left, right = 0, len(nums)-1
        while left < right:
            mid = (left + right) // 2
            if mid % 2 == 1: mid -= 1
            if nums[mid] == nums[mid+1]:
                left = mid + 2
            else:
                right = mid
        return nums[left]

# C++
class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            if (mid % 2 == 1)
                mid--;
            if (nums[mid] == nums[mid+1])
                left = mid + 2;
            else
                right = mid;
        }
        return nums[left];
    }
};
4. 发现第一个错误版本

LeetCode 278. First Bad Version (Easy)

# Python
# The isBadVersion API is already defined for you.
# @param version, an integer
# @return an integer
# def isBadVersion(version):

class Solution:
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        left, right = 0, n
        while left <= right:
            mid = (left + right) // 2
            if isBadVersion(mid):
                right = mid - 1
            else:
                left = mid + 1
        return left
    
# C++
# The API isBadVersion is defined for you.
# bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        long int left = 0, right = n;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (isBadVersion(mid))
                right = mid - 1;
            else
                left = mid + 1;
        }
        return left;
    }
};
5. 寻找升序数组的旋转点

LeetCode 153. Find Minimum in Rotated Sorted Array (Medium)

方法一:遍历数组,分别讨论只有一个元素,和数组为生序序列的情况,时间复杂度 O ( n ) O(n) O(n)

方法二:二分搜索,时间复杂度 O ( log ⁡ n ) O(\log n) O(logn)

# Python 方法一
class Solution:
    def findMin(self, nums: List[int]) -> int:
        if len(nums) == 1: return nums[0]
        for i in range(1, len(nums)):
            if nums[i] > nums[i-1]:
                continue
            else:
                return nums[i]
        return nums[0]
# Python 方法二
class Solution:
    def findMin(self, nums: List[int]) -> int:
        left, right = 0, len(nums)-1
        while left < right:
            mid = (left + right) // 2
            if nums[mid] <= nums[right]:
                right = mid
            else:
                left = mid + 1
        return nums[left]
# C++ 方法二

6. 在升序序列中寻找某一值的区间

LeetCode 34. Find First and Last Position of Element in Sorted Array (Medium)

# Python
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if not nums: return [-1, -1]
        
        left, right = 0, len(nums)-1
        while left < right:
            mid = (left + right) // 2
            if nums[mid] == target:
                return self.findBoundary(nums, mid)
            if nums[mid] < target:
                left = mid + 1
            else:
                right = mid
        if nums[left] == target:
            return [left, left]
        else:
            return [-1, -1]
    
    def findBoundary(self, nums, position):
        left = right = position
        while left > 0 and nums[left] == nums[left-1]:
            left -= 1
        while right < len(nums)-1 and nums[right] == nums[right+1]:
            right += 1
        return [left, right]
# C++

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值