leetcode刷题笔记-binary search

标准的bs:

def binary_search(arr, target):
    l, r = 0, len(arr) - 1
    while l < r:
        mid = l + (r - l) // 2
        if arr[mid] < target:
            l = mid + 1
        else:
            r = mid
    return r  # 返回的是右侧的
例子
【1,2,2,3】 target 2.1
返回的是3的位置

1885. Count Pairs in Two Arrays

 

class Solution:
    def countPairs(self, nums1: List[int], nums2: List[int]) -> int:
        '''
nums1[i] + nums1[j] > nums2[i] + nums2[j] is the same as (nums1[i] - nums2[i]) + (nums1[j] - nums2[j]) > 0

So, if we define NUM = [nums1[0]-nums2[0], nums1[1]-nums2[1], ...],
This problem can be rewritten as:
How many (i, j) pairs with i < j that NUM[i] + NUM[j] > 0
Given a value x, count the number of y in the nums that satisfies (y + x > 0)  -> Binary search
Time: n*log(n)
Space: O(n) if we copy the given nums, or O(1)
        '''

        nums = [x-y for x, y in zip(nums1, nums2)]
        re = 0
        nums.sort()

        def binary(target):
            l, r = 0, len(nums)
            while l < r:
                mid = (l+r) // 2
                if nums[mid] < target:
                    l = mid + 1
                else:
                    r = mid
            return l
        # print(nums)
        for i, x in enumerate(nums):
            target = 0 - x + 0.1
            idx = binary(target)
            # print("x", x, "target", target, "idx", idx)
            re += len(nums) - max(idx, i+1)  # 为什么要max, nums = [-1, -1, 1, 1], i=2, x= 1的时候, idx = 2,避开自己和自己pair,和自己和后面那个1匹配,后面那个1又和前面这个1重复匹配的情况
        return re

1287. Element Appearing More Than 25% In Sorted Array

class Solution:
    def findSpecialInteger(self, arr: List[int]) -> int:
        for i in range(4):
            target = arr[len(arr)//4 *i] # find the 0, 25, 50, 75% 肯定在这4个位置中的某一个
            
            # binary search to find left most
            l, r = 0, len(arr) - 1
            target = target - 0.1
            while l < r: 
                mid = l + (r - l) // 2
                if arr[mid] < target: l = mid + 1
                else: r = mid
            
            if l + len(arr) // 4 < len(arr) and arr[l+len(arr)//4] == arr[l]:
                return arr[l]

1287. Element Appearing More Than 25% In Sorted Array

class Solution:
    def findSpecialInteger(self, arr: List[int]) -> int:
        for i in range(4):
            target = arr[len(arr)//4 *i] # find the 0, 25, 50, 75% 肯定在这4个位置中的某一个
            
            # binary search to find left most
            l, r = 0, len(arr) - 1
            target = target - 0.1
            while l < r: 
                mid = l + (r - l) // 2
                if arr[mid] < target: l = mid + 1
                else: r = mid
            
            if l + len(arr) // 4 < len(arr) and arr[l+len(arr)//4] == arr[l]:
                return arr[l]

1201. Ugly Number III

Loading...

class Solution:
    def nthUglyNumber(self, n: int, a: int, b: int, c: int) -> int:
        '''
        https://leetcode.com/problems/ugly-number-iii/discuss/387780/JavaC%2B%2B-Binary-Search-with-Venn-Diagram-Explain-Math-Formula
        num/a + num/b + num/c – num/lcm(a, b) – num/lcm(b, c) – num/lcm(a, c) + num/lcm(a, b, c)

        '''
        
        def gcd(a, b):
            if a == 0: return b
            return gcd(b % a, a)
        
        def lcm(a, b):
            return a * b / gcd(a, b)
        
        
        def count(a, b, c, num):
            return num // a + num // b + num // c - num // lcm(a, b) - num // lcm(b, c) - num // lcm (a, c) + num // lcm(a, lcm(b, c))
        
        
        left = 0
        right = 2*10**9
        
        while left <right:
            mid = (left + right) // 2
            if count(a, b, c, mid) < n:
                left = mid + 1
            else:
                right = mid
        return left
                

1231. Divide Chocolate

class Solution:
    def maximizeSweetness(self, A: List[int], K: int) -> int:
        left, right = 1, sum(A) // (K + 1)  # right就是我最多能拿到的swetness
        while left < right:
            mid = (left + right + 1) // 2
            cur = cuts = 0  # 每份都有mid个,总共能分多少个cuts
            for a in A:
                cur += a
                if cur >= mid:
                    cuts += 1
                    cur = 0
            if cuts > K:  # 能分大于K个cuts,可能更多,说明我其实可能可以拿更多sweetness
                left = mid
            else:
                right = mid - 1
        return right

410. Split Array Largest Sum 

还有一种dp的解法,没有二分法好,写在dp分类里面 

思路:Loading...  

用Go写的:

func splitArray(nums []int, m int) int {
    // binary search
    max := 0
    sum := 0
    
    for _, v := range nums {
        sum += v
        if v > max {
            max = v
        }
    }
    
    l, r := max, sum
    for l <= r {
        mid := l + (r-l) / 2
        if valid(nums, mid, m) {
            r = mid - 1  // mid 要尽量小
        }else{
            l = mid + 1
        }
        
    }
    
    return l
}


func valid(nums []int, target int, m int) bool {
    count := 1  // count to m, if count can make to m then it is valid
    total := 0  // sum of subarray should <= than target
    for _, v := range nums{
        total += v
        if total > target {
            total = v
            count += 1
            
            if count > m {
                return false
            }
        }
        
    }
    return true
    
}

287. Find the Duplicate Number

nlogn 

class Solution(object):
    def findDuplicate(self, nums):
        l, r = 1, len(nums) - 1
        while l < r:
            mid = (l+r) / 2
            count = 0
            for n in nums:
                if n <= mid:
                    count += 1
            if count > mid:
                r = mid
            else:
                l = mid + 1
        return l

4. Median of Two Sorted Arrays

好像是当初算法期末考里面的一题, 现在又不懂了。

Loading...

It's guaranteed to be O(log(min(m,n))  每次从A cut 一些, 最多cut len(A)次就被cut完了。  

A[i] B[j]相当于medium1 和 medium2. 二分查找法就是使得medium1=medium2 如果med1> med2 那么med1就应该是在小的那一半,med2在大的一半。 这样med1才会变小,med2才会变大。 

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        def findKth(A, B, K):
            if len(A) > len(B):
                A, B = B, A
            
            if not A: return B[K]
            if K == len(A) + len(B) - 1: return max(A[-1], B[-1])
            
            i = min(len(A)-1, K / 2)
            j = min(len(B)-1, K - i)
            
            if A[i] > B[j]:
                return findKth(A[:i], B[j:], i)  # i 是因为 B删掉了j个 K-j = i
            else:
                return findKth(A[i:], B[:j], j)
            
        l = len(nums1) + len(nums2)
        return findKth(nums1, nums2, l / 2) if l % 2 else (findKth(nums1, nums2, l/2 -1) + findKth(nums1, nums2, l/2)) / 2.0

540. Single Element in a Sorted Array 

   public static int singleNonDuplicate(int[] nums) {
        int start = 0, end = nums.length - 1;

        while (start < end) {
            // We want the first element of the middle pair,
            // which should be at an even index if the left part is sorted.
            // Example:
            // Index: 0 1 2 3 4 5 6
            // Array: 1 1 3 3 4 8 8
            //            ^
            int mid = (start + end) / 2;
            if (mid % 2 == 1) mid--;

            // We didn't find a pair. The single element must be on the left.
            // (pipes mean start & end)
            // Example: |0 1 1 3 3 6 6|
            //               ^ ^
            // Next:    |0 1 1|3 3 6 6
            if (nums[mid] != nums[mid + 1]) end = mid;

            // We found a pair. The single element must be on the right.
            // Example: |1 1 3 3 5 6 6|
            //               ^ ^
            // Next:     1 1 3 3|5 6 6|
            else start = mid + 2;
        }

        // 'start' should always be at the beginning of a pair.
        // When 'start > end', start must be the single element.
        return nums[start];
    }

 34. Find First and Last Position of Element in Sorted Array

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if not nums:
            return [-1, -1]
        
        def binary_search(nums, target):
            left, right = 0, len(nums)-1
            while left < right:
                mid = (left+right) // 2
                if target < nums[mid]:
                    right = mid
                else:
                    left = mid + 1
            return left  
        
        start = binary_search(nums, target-0.5)
        if nums[start] != target:
            return [-1, -1]
        
        end = binary_search(nums+[0], target+0.5) - 1
        return [start, end]

33. Search in Rotated Sorted Array

2分查找法

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1
class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if not nums:
            return -1
        
        left, right = 0, len(nums)-1
        
        while left<=right:
            mid = (left+right) // 2
            print left, right, mid
            if nums[mid] == target:
                return mid
            
            if nums[left] <= nums[mid]:
                if nums[left] <= target < nums[mid]:
                    right = mid-1
                else:
                    left = mid+1
            else:
                if nums[mid] < target <= nums[right]:
                    left = mid+1
                else:
                    right = mid-1
        
        return -1

81. Search in Rotated Sorted Array II

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).

You are given a target value to search. If found in the array return true, otherwise return false.

Example 1:

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

Example 2:

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

和上一题的区别只是多了一种 nums[left]=nums[mid]=nums[right]的情况需要考虑。

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: bool
        """
        if not nums:
            return False
        
        left, right = 0, len(nums)-1
        
        while left<=right:
            mid = (left+right) // 2  
            if nums[mid] == target:
                return True
            if nums[left] == nums[mid] and nums[mid] == nums[right]:
                left += 1
                right -= 1
                continue
            
            if nums[left] <= nums[mid]:
                if nums[left] <= target < nums[mid]:
                    right = mid-1
                else:
                    left = mid+1
            else:
                if nums[mid] < target <= nums[right]:
                    left = mid+1
                else:
                    right = mid-1
        
        return False

528. Random Pick with Weight

class Solution(object):
    def __init__(self, w):
        
        self.s = sum(w)
        self.w = w
        self.n = len(w)
        for i in xrange(1, len(w)):
            w[i] += w[i-1]
        
    def pickIndex(self):
        seed = random.randint(1, self.s)  # value
        l, r = 0, self.n-1  # index
        while l < r:  # 找到seed 在哪个区间
            mid = (l+r) / 2
            if self.w[mid] < seed:  # 没有等于
                l = mid + 1
            else:
                r = mid
        return l 

162. Find Peak Element

binary search

找local最大值,如果mid < mid+1 left肯定要移到Mid+1来才能保证结果在右边。 答案是返回left 或者right 因为要考虑 【1】这种没有mid的情况

class Solution(object):
    def findPeakElement(self, nums):
        left = 0
        right = len(nums) - 1
        
        while left < right:
            mid = (left+right) / 2
            
            if nums[mid] < nums[mid+1]:
                left = mid + 1
            else:
                right = mid
                
        return left

658. Find K Closest Elements

按直觉做的解法,但不是最优的。最优的解法 直接找到最低的idx然后返回arr[idx, idx+K]

class Solution(object):
    def findClosestElements(self, arr, k, x):
        # use binary search to find the cloest idx first and then using two pointer to find the rest
        l = 0
        r = len(arr) - 1
        
        while l < r - 1:
            m = (l + r) / 2
            if arr[m] <= x:
                l = m
            else:
                r = m - 1
       
        idx = l if abs(x-arr[l]) <= abs(x-arr[r]) else r
        res = [arr[idx]]
        k = k - 1
        # two pointer
        l, r = idx-1, idx+1
        while k > 0:
            # print res
            if l >= 0 and r < len(arr):
                if abs(x-arr[l]) <= abs(x-arr[r]):
                    res = [arr[l]] + res
                    l -= 1
                else:
                    res.append(arr[r])
                    r += 1
                k -= 1
            elif l < 0 and r < len(arr):
                res.append(arr[r])
                r += 1
                k -= 1
            elif l >= 0 and r >= len(arr):
                res = [arr[l]] + res
                l -= 1
                k -= 1
            else:
                break
        
        return res
public List<Integer> findClosestElements(List<Integer> arr, int k, int x) {
    int lo = 0, hi = arr.size() - k;
    while (lo < hi) {
        int mid = (lo + hi) / 2;
        if (x - arr.get(mid) > arr.get(mid+k) - x)
            lo = mid + 1;
        else
            hi = mid;
    }
    return arr.subList(lo, lo + k);
}

793. Preimage Size of Factorial Zeroes Function

Loading...

time complexity is O((logK)^2) and space complexity is O(1).

class Solution(object):
    def preimageSizeFZF(self, K):

        def numberOfTrailingZeros(x):
            res = 0
            while x > 0:
                res += x / 5
                x /= 5
            return res
        
        def binarySearch(k):
            l, r = 0, 5*(k+1)  #  find the largest integers so need + 1
            
            while l <= r:
                m = l + (r-l) / 2
                zero = numberOfTrailingZeros(m)
                
                if zero <= k:  # <= to find the largest
                    l = m + 1
                else:
                    r = m - 1
            return r
                
        return binarySearch(K) - binarySearch(K-1)

74. Search a 2D Matrix

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix:
            return False
        
        return self.helper(0, len(matrix)-1, matrix, target)  
    
    def helper(self, start, end, matrix, target):
      
        if start == end:
            for n in matrix[start]:
                if n == target:
                    return True
            else:
                return False
        
        midRow = (end + start)/2
        if not matrix[midRow]: return False
        mid = matrix[midRow][-1]  
        if target > mid:
            return self.helper(midRow+1, end, matrix, target)
        else:
            return self.helper(start, midRow, matrix, target)

240. Search a 2D Matrix II

We start search the matrix from top right corner, initialize the current position to top right corner, if the target is greater than the value in current position, then the target can not be in entire row of current position because the row is sorted, if the target is less than the value in current position, then the target can not in the entire column because the column is sorted too. We can rule out one row or one column each time, so the time complexity is O(m+n).

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix:
            return False
        
        row, col = len(matrix)-1, len(matrix[0])-1
        i, j = 0, col
        
        while 0 <= i <= row and 0 <= j <= col:
            if matrix[i][j] > target:
                j -= 1
            elif matrix[i][j] < target:
                i += 1
            else:
                return True
        return False

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值