Leetcode Title (Binary Search)

Posted by brynjar on Wed, 24 Nov 2021 18:56:22 +0100

This article is based on Datewhale Phase 31 Team Learning

Binary Lookup Code:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        # Find target within interval [left, right]
        while left <= right:
            # Take Interval Middle Node
            mid = (left + right) // 2
            # If the target value is found, return directly to the center location
            if nums[mid] == target:
                return mid
            # If nums[mid] is less than the target value, continue searching in [mid + 1, right]
            elif nums[mid] < target:
                left = mid + 1
            # If nums[mid] is larger than the target value, continue searching in [left, mid-1]
            else:
                right = mid - 1
        # No elements were searched, returning -1
        return -1

 

        1. About left <= right and left < right:

  • If the statement is   Left <= right, and the element found does not exist, then   while   The condition for judging a statement to be out of bounds is   left == right + 1, written as an interval is   [right + 1, right], the interval to be searched is empty, there are no elements in the interval to be searched, so terminating the loop can return directly  - 1   Yes.    
  • If the judgement statement is left < right and the element found does not exist,   while   The condition for judging a statement to be out of bounds is   left == right, written as an interval is   [right, right]. In this case, the interval is not empty, there is still an element in the interval to be searched, and it is not certain that the element to be searched is not in this interval, then the loop terminates and returns  - 1   Is wrong.          

        For example, intervals   [2, 2], element   2   It belongs to this interval, terminates the cycle, returns  - 1   That element is missing.

        In the face of this situation, you can add a layer of judgment and judgment when returning.   left   Does the pointed position equal the target element, and if so returns   left, return if not  - 1

        In addition, use   left < right   The other benefit of this is when you exit the loop   left == right   If so, you don't have to decide that you should go back   left   still   Right   Yes.

        2.   Two Ideas for Binary Search

  • Find directly

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        # Find target within interval [left, right]
        while left <= right:
            # Take Interval Middle Node
            mid = left + (right - left) // 2
            # If the target value is found, the direct range center location
            if nums[mid] == target:
                return mid
            # If nums[mid] is less than the target value, continue searching in [mid + 1, right]
            elif nums[mid] < target:
                left = mid + 1
            # If nums[mid] is larger than the target value, continue searching in [left, mid-1]
            else:
                right = mid - 1
        # No elements were searched, returning -1
        return -1
  •   Exclusion Method

Code 1:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        # Find target within interval [left, right]
        while left < right:
            # Take Interval Middle Node
            mid = left + (right - left) // 2
            # nums[mid] is smaller than the target value, excluding the impossible interval [left, mid], and continue searching in [mid + 1, right]
            if nums[mid] < target:
                left = mid + 1 
            # nums[mid] is greater than or equal to the target value, the target element may continue searching in [left, mid]
            else:
                right = mid
        # Determines whether the remaining elements of an interval are the target elements, not returns -1
        return left if nums[left] == target else -1

 

Code 2:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        # Find target within interval [left, right]
        while left < right:
            # Take Interval Middle Node
            mid = left + (right - left + 1) // 2
            # nums[mid] is larger than the target value, excluding the impossible interval [mid, right], and continue searching in [left, mid-1]
            if nums[mid] > target:
                right = mid - 1 
            # nums[mid] is less than or equal to the target value, the target element may continue searching in [mid, right]
            else:
                left = mid
        # Determines whether the remaining elements of an interval are the target elements, not returns -1
        return left if nums[left] == target else -1
  • You can remember about boundary settings as follows:As long as you see   left = mid   Round up. That is:
    • left = mid + 1   and   right = mid   and   mid = left + (right - left) // 2   Must be paired.
    • Right = mid-1   and   left = mid   and   mid = left + (right - left + 1) // 2   Must be paired.

Title:

0704. Find   

Given a   n   Ordered (ascending) integer array of elements   nums and a target value   Target  , Write a function search   nums   If the target value has a return subscript, otherwise it returns -1.

Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Interpretation: 9 appears in nums with subscript 4

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        length = len(nums)
        l = 0
        r = length - 1
        while l <= r :
            mid = (l + r)//2
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                l = mid + 1
            else :
                r = mid - 1
        return -1

 

0035. Search insert location  

Given a sorted array and a target value, find the target value in the array and return its index. If the target value does not exist in the array, return the position where it will be inserted sequentially.

You must use an algorithm with O(log n) time complexity.

Input: nums = [1,3,5,6], target = 5
Output: 2

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        length = len(nums)
        l = 0
        r = length - 1
        while l <= r:
            mind = (l + r)//2
            if nums[mind] == target:
                return mind
            elif nums[mind] < target:
                l = mind + 1
            else :
                r = mind - 1 
        return l

 

0374. Guess the number         

The rules for guessing a number game are as follows:

For every game, I play from   1   reach   n Randomly select a number. Please guess which number was selected.
If you make a mistake, I'll tell you if your guess is larger or smaller than the one I selected.
You can get a guess by calling a predefined interface, int guess(int num), and the return value has three possible scenarios (-1,1)   Or 0:

-1: I chose a number smaller than what you guessed < num
1: I chose a number larger than your guess pick > num
0: I chose the same number as you guessed. Congratulations! Bingo! pick == num
Return the number I selected.

Input: n = 10, pick = 6
Output: 6

# 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:
        left, right = 1, n
        
        while left <= right:
            mid = (left + right) // 2
            if not guess(mid):
                return mid
            elif guess(mid) == -1:
                right = mid - 1
            else:
                left = mid + 1

 

0069. Sqrt(x)  

Give you a non-negative integer x, calculate and return   X   The arithmetic square root of.

Since the return type is an integer, only the integer part of the result is retained, and the decimal part is discarded.

Note: No built-in exponential functions and operators, such as pow(x, 0.5) or x ** 0.5, are allowed.

Input: x = 4
 Output: 2

 

class Solution:
    def mySqrt(self, x: int) -> int:
        l = 0
        r = x
        while l <= r:
            mid = (l + r)//2
            m = mid * mid 
            n = (mid + 1) * (mid + 1)
            if m <= x:
                if n == x:
                    return mid + 1
                elif n > x:
                    return mid
                else:
                    l = mid + 1
            else :
                r = mid - 1

0167.Sum of Two Numbers II - Transfer Ordered Array      

Given a sorted in non-decreasing order    Array of integers   Number, please find out from the array that the sum of two numbers is equal to the target number   Target.

The function should return the subscript values of these two numbers as an array of integers of length 2. Numbers'subscripts count from 1, so the answer array should satisfy 1 <= answer[0] < answer[1] <= numbers.length.

You can assume that each input corresponds to a unique answer, and that you cannot reuse the same elements.

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 equals the target number 9. So index1 = 1, index2 = 2.

 

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        l, r = 0, len(numbers) - 1
        while l <= r:
            if numbers[l] + numbers[r] == target:
                return [l + 1, r + 1 ]
            elif numbers[l] + numbers[r] < target:
                l += 1
            else:
                r -= 1

1011. Delivery of packages within D days    

Parcels on conveyor belts must be transported from one port to another within D days.

I on conveyor belt   The weight of each package is   weights[i]. Every day, we load packages onto conveyor belts in the order of weight given. We will not carry more weight than the maximum carrying weight of the ship.

Returns the minimum carrying capacity of a ship capable of delivering all packages on a conveyor belt within D days.

Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5
Output: 15
Explanation:
Ships with a minimum load of 15 will be able to deliver all packages within five days, as follows:
Day 1: 1, 2, 3, 4, 5
Day 2: 6, 7
Day 3: 8
Day 4: 9
Day 5:10

Please note that the goods must be shipped in the given order, so it is not allowed to use a ship with a capacity of 14 and divide the package into (2, 3, 4, 5), (1, 6, 7), (8), (9), (10).

  Author's Note: If this question was not written about my first reaction DP during the practice of binary search, it was later found that DP would time out,,,

class Solution:
    def shipWithinDays(self, weights: List[int], days: int) -> int:
        # If it weren't for the dichotomy search,,,,,,,,
        left = max(weights)
        right = sum(weights)  # Transportation must be between max(weights) and sum(weights)
        while left <= right:
            mid = (left + right)//2
            day, num = 1, 0
            for i in weights:
                num += i
                if num > mid:
                    num = i 
                    day += 1
            if day > days:  # Notice the boundary
                left = mid + 1
            elif day <= days:  # Can't guarantee equality is where minimum capacity is, so change to right
                right = mid - 1
        return left

 

0278.The wrong version  

You are the product manager and are currently leading a team to develop new products. Unfortunately, the latest version of your product has not passed the quality test. Since each version was developed based on a previous version, all versions after the wrong version are incorrect.

Suppose you have n versions [1, 2,..., n], and you want to find the first version that caused all subsequent versions to fail.

You can call   bool isBadVersion(version)   The interface determines if the version number version is in error in the unit test. Implement a function to find the first wrong version. You should minimize the number of calls to the API.

Input: n = 5, bad = 4
Output: 4
Explanation:
Call isBadVersion (3) -> false  
Call isBadVersion(5)  -> True  
Call isBadVersion(4)  -> True
So, 4 is the first wrong version.

# 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
        """
        l, r = 1, n
        while l <= r:
            mid = (l + r)//2
            if isBadVersion(mid):
                r = mid - 1
            else:
                l = mid + 1
        return l

 

0033. Search for Rotated Sort Array     

The integer array nums is arranged in ascending order, and the values in the array are different from each other.

Nums rotates an array to [nums[k], nums[k+1],..., nums[n-1], nums[0], nums[1],..., nums[1],..., nums[k-1] (subscripts count from 0) before passing it to the function. For example, [0,1,2,4,5,6,7] may become rotated at subscript 3   [4,5,6,7,0,1,2].

Give you a rotated array of nums and an integer target, if the target value exists in nums, return its subscript, otherwise return  - 1  .

Input:nums = [4,5,6,7,0,1,2], target = 0
Output:4
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = (l + r)//2
            if nums[mid] == target:
                return mid
            # Divided into ordered and disordered
            elif nums[mid] < nums[r]:  # mid Right Ordered
                if nums[mid] < target and nums[r] >= target:  # Goals in order
                    l = mid + 1
                else:
                    r = mid - 1
            else:  # mid Left Ordered
                if nums[mid] > target and nums[l] <= target:  # Goals in order 
                    r = mid - 1
                else:
                    l = mid + 1
        return -1

 

0153. Find the most value in a rotated sort array      

An array with a known length of n is pre-sorted in ascending order and rotated 1 to N times to obtain an input array. For example, the original array nums = [0,1,2,4,5,6,7] may get after changing:
If you rotate it four times, you get [4,5,6,7,0,1,2]
If you rotate it seven times, you get [0,1,2,4,5,6,7]
Notice that the result of one rotation of the array [a[0], a[1], a[2],..., a[n-1]] is the array [a[n-1], a[0], a[1], a[2],..., a[n-2].

You are given an array of nums elements with different values, which was originally an ascending array and rotated several times as described above. Please find and return the smallest element in the array.

Input: nums = [3,4,5,1,2]
Output: 1
 Explanation: The original array is [1,2,3,4,5], rotate three times to get the input array.
class Solution:
    def findMin(self, nums: List[int]) -> int:
        l, r = 0, len(nums) - 1
        while l < r:
            mid = (l + r)//2
            if nums[mid] <= nums[r]: 
                r = mid  # Minimum on the left side of mid or mid itself
            else:
                l = mid + 1  # Minimum must be on the right side of mid
        return nums[l]

 

   Reference Links LeetCode for Algorithms | LeetCode for Algorithms

                Force buckle

Topics: Python leetcode