Algorithm Study Notes 1: Binary Search

1. Binary search

  • sorted, or indirectly sorted
  • Pay attention to the boundary conditions, since only one condition is triggered per loop, so iii orjjj can only move one step, the loop condition isi ≤ ji\le jij
training plan

Subject: 704. Binary Search

Code template:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        i, j = 0, len(nums)-1
        while i <= j:
            # 取靠左的,即 1 2 3 4 取2,1 2 3 取2
            # 防止计算时溢出
            mid = i + ((j-i) >> 1)
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                i = mid+1
            else:
                j = mid-1
        return -1

Title: 278. The first wrong version

Code template:

# 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
        """
        # 特殊之处在于只有2种状态,即当跳出循环时:
        # 如果是i未出错,i += 1,返回i;如果j未出错,一定是上一个版本出错,也返回i
        i, j = 1, n
        while i <= j:
            mid = i + ((j-i) >> 1)
            if isBadVersion(mid):
                j = mid-1
            else:
                i = mid+1
        return i

This question can also use i < j i<ji<The condition of j is judged, and only one pointer moves at a time.

Why is there such a difference ? In fact, it is because of the different interval conditions of dichotomy. There are 3 situations for judging the number. When the final range length is greater than 0, it is the valid range; but there are only 2 cases for judging true or false. Only when the range length is 1 is the final answer. Here we need to think carefully and generalize the problem to various situations.

Topic: 35. Search insertion position

Code template:

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        # 3种情况,对比普通二分将返回-1变为返回合适的索引
        # 考虑找不到的情况,此时i=j,并且有一个变化使while条件不成立,大了j减1,小了i+1,所以返回i
        # 插入位置i表示插入到i索引之前
        i, j = 0, len(nums)-1
        while i <= j:
            mid = i + ((j-i) >> 1)
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                i = mid+1
            else:
                j = mid-1
        return i
similar topic

Topic: 34. Find the first and last position of an element in a sorted array (emphasis)

Code template:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        # i和j就是区间2端点
        # 3种情况
        i, j = 0, len(nums)-1
        while i <= j:
            mid = i + ((j-i) >> 1)
            if nums[mid] < target:
                i = mid + 1
            elif nums[mid] > target:
                j = mid - 1
            # mid到j都等于target
            elif nums[i] != target:
                i += 1
            # i到mid都等于target
            elif nums[j] != target:
                j -= 1
            else:
                return [i, j]
        return [-1, -1]

This question is more interesting. My implementation is not a complete binary search, but to a certain extent, the use of binary search optimizes the overall efficiency. If you have time, you can learn the official solution

Topic: 374. Guessing the Size of Numbers

Code template:

# The guess API is already defined for you.
# @param num, your guess
# @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
# def guess(num: int) -> int:

class Solution:
    def guessNumber(self, n: int) -> int:
        i, j = 1, n
        while i <= j:
            mid = i + ((j-i) >> 1)
            if guess(mid) == 0:
                return mid
            elif guess(mid) == -1:
                j = mid-1
            else:
                i = mid+1
        # 返回0表示pick不在范围内
        return 0

Topic: 658. Find the K closest elements (check the coding ability)

Code template:

class Solution:
    def findClosestElements(self, arr: List[int], k: int, x: int) -> List[int]:
        # 二分找到恰好大于x一点点的位置,等价于之前的查找插入位置
        i, j = 0, len(arr)-1
        idx = -100
        while i <= j:
            mid = i + ((j-i) >> 1)
            if arr[mid] == x:
                idx = mid
                break
            elif arr[mid] < x:
                i = mid+1
            else:
                j = mid-1
        if idx == -100:
            idx = i
        # print(idx)
        # 缩小区间
        if idx == 0:
            return arr[:k]
        elif idx == len(arr):
            return arr[-k:]
        else:
            i, j = max(idx-k, 0), min(idx+k, len(arr)-1)
            while j-i >= k:
                if arr[j] - x > x - arr[i]:
                    j -= 1
                elif arr[j] - x < x - arr[i]:
                    i += 1
                else:
                    j -= 1
            return arr[i:j+1]

Guess you like

Origin blog.csdn.net/qq_45510888/article/details/123610830