classSolution: defsearch(self, nums: List[int], target: int) -> bool: l = 0 r = len(nums) - 1 while l <= r: mid = l + (r-l) // 2 if nums[mid] == target: returnTrue if nums[l] == nums[mid]: l += 1 continue if nums[mid] < nums[l]: if nums[mid] < target <= nums[r]: l = mid + 1 else: r = mid - 1 else: if nums[l] <= target < nums[mid]: r = mid - 1 else: l = mid + 1 returnFalse
153. Find Minimum in
Rotated Sorted Array
反转列表找出最小值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Example 1: Input: nums = [3,4,5,1,2] Output: 1 Explanation: The original array was [1,2,3,4,5] rotated 3 times.
Example 2: Input: nums = [4,5,6,7,0,1,2] Output: 0 Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.
Example 3: Input: nums = [11,13,15,17] Output: 11 Explanation: The original array was [11,13,15,17] and it was rotated 4 times.
面试碰到了, 细分情况没分出来, 其实正确做法是以最后一个元素为坐标来找.
半开半闭返回l即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: deffindMin(self, nums: List[int]) -> int: n = len(nums) l = 0 r = n - 1 while l < r: mid = l + (r-l) // 2 # min在右侧 if nums[mid] > nums[-1]: l = mid + 1 # min在左侧或者直接是mid else: r = mid return nums[l]
154. Find Minimum in
Rotated Sorted Array II
同上题, 但是包含重复, 重复项的解决和之前那题一样, 扫到了直接
r -= 1 即可. 下面的代码可以继续合并elif,
不过这样更直观一些.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: deffindMin(self, nums: List[int]) -> int: l = 0 r = len(nums) - 1 while l < r: mid = l + (r-l) // 2 if nums[mid] == nums[r]: r -= 1 continue if nums[mid] > nums[r]: l = mid + 1 else: r = mid return nums[l]
34.
Find First and Last Position of Element in Sorted Array
比较经典的二分, 注意找到值的时候仅 nums[mid] < target
才做 l = mid + 1, 否则 r = mid - 1,
这样才能找到左值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defbinsearch(self, nums, target): l = 0 r = len(nums) - 1 while l <= r: mid = l + (r-l) // 2 if nums[mid] < target: l = mid + 1 else: r = mid - 1 return l
defsearchRange(self, nums: List[int], target: int) -> List[int]: start = self.binsearch(nums, target) if start == len(nums) or nums[start] != target: return [-1, -1] end = self.binsearch(nums, target+1) return [start, end - 1]
69. Sqrt(x)
字面意思, 求开方
二分
1 2 3 4 5 6 7 8 9 10 11
classSolution: defmySqrt(self, x: int) -> int: l = 0 r = x while l <= r: mid = l + (r-l) // 2 if mid*mid > x: r = mid - 1 else: l = mid + 1 return r
牛顿法
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defmySqrt(self, x: int) -> int: b = x while b*b > x: # y = y0 + y'(x-x0) # -> x0 - x = y0 / y' # -> x = x0 - y0 / y' # 而y = x^2 - target # -> x = x0 - (x0^2 - target) / 2x0 # -> x = 0.5x0 + target / 2x0 # -> x = (x0 + target/x0) / 2 b = (b + x//b) // 2 return b
162. Find Peak Element
A peak element is an element that is strictly
greater than its neighbors.
Given a 0-indexed integer array nums, find a peak
element, and return its index. If the array contains multiple peaks,
return the index to any of the peaks.
You may imagine that nums[-1] = nums[n] = -∞. In other
words, an element is always considered to be strictly greater than a
neighbor that is outside the array.
You must write an algorithm that runs in O(log n)
time.
然后限制条件 nums[i] != nums[i + 1] for all valid i.
1 2 3 4 5 6 7 8 9
Example 1: Input: nums = [1,2,3,1] Output: 2 Explanation: 3 is a peak element and your function should return the index number 2.
Example 2: Input: nums = [1,2,1,3,5,6,4] Output: 5 Explanation: Your function can return either index number 1 where the peak element is 2, or index number 5 where the peak element is 6.
classSolution: defbinsearch(self, nums, target): l = 0 r = len(nums) - 1 while l <= r: mid = l + (r-l) // 2 if nums[mid] == target: return mid elif nums[mid] > target: r = mid - 1 else: l = mid + 1 return l
defsearchMatrix(self, matrix: List[List[int]], target: int) -> bool: m = len(matrix) n = len(matrix[0]) col = n for row inrange(m): col = self.binsearch(matrix[row][:col], target) if col < n and matrix[row][col] == target: returnTrue returnFalse
classSolution: defmaxRow(self, mat, col): idx = -1 v = -1 for row inrange(len(mat)): if mat[row][col] > v: v = mat[row][col] idx = row return idx
deffindPeakGrid(self, mat: List[List[int]]) -> List[int]: n = len(mat[0])
l = 0 r = n - 1 while l <= r: mid = l + (r-l) // 2 row = self.maxRow(mat, mid) left = mat[row][mid-1] if mid > 0else -1 right = mat[row][mid+1] if mid < n - 1else -1
if mat[row][mid] < left: r = mid - 1 elif mat[row][mid] < right: l = mid + 1 else: return [row, mid]
540. Single Element in a
Sorted Array
You are given a sorted array consisting of only integers where every
element appears exactly twice, except for one element which appears
exactly once.
Return the single element that appears only once.
Your solution must run in O(log n) time and O(1) space.
1 2 3 4 5 6 7
Example 1: Input: nums = [1,1,2,3,3,4,4,8,8] Output: 2
Example 2: Input: nums = [3,3,7,7,10,11,11] Output: 10
classSolution: defsingleNonDuplicate(self, nums: List[int]) -> int: n = len(nums) l = 0 r = n - 1 while l < r: mid = l + (r-l) // 2 odd = (mid - l) % 2 if odd: if nums[mid] == nums[mid-1]: l = mid + 1 else: r = mid - 1 else: if nums[mid] == nums[mid-1]: r = mid - 2 elif nums[mid] == nums[mid+1]: l = mid + 2 else: return nums[mid] return nums[l]
2513. Minimize the Maximum
of Two Arrays
We have two arrays arr1 and arr2 which are
initially empty. You need to add positive integers to them such that
they satisfy all the following conditions:
arr1 contains uniqueCnt1 distinct positive
integers, each of which is not divisible by divisor1.
arr2 contains uniqueCnt2 distinct positive
integers, each of which is not divisible by divisor2.
No integer is present in both arr1 and
arr2.
Given divisor1, divisor2, uniqueCnt1, and uniqueCnt2, return the
minimum possible maximum integer that can be present in either
array.
Example 1: Input: divisor1 = 2, divisor2 = 7, uniqueCnt1 = 1, uniqueCnt2 = 3 Output: 4 Explanation: We can distribute the first 4 natural numbers into arr1 and arr2. arr1 = [1] and arr2 = [2,3,4]. We can see that both arrays satisfy all the conditions. Since the maximum value is 4, we return it.
Example 2: Input: divisor1 = 3, divisor2 = 5, uniqueCnt1 = 2, uniqueCnt2 = 1 Output: 3 Explanation: Here arr1 = [1,2], and arr2 = [3] satisfy all conditions. Since the maximum value is 3, we return it.
Example 3: Input: divisor1 = 2, divisor2 = 4, uniqueCnt1 = 8, uniqueCnt2 = 2 Output: 15 Explanation: Here, the final possible arrays can be arr1 = [1,3,5,7,9,11,13,15], and arr2 = [2,6]. It can be shown that it is not possible to obtain a lower maximum satisfying all conditions.
除了题目描述以外, 算是个好题, 二分思路, 找上下界,
mid满足的时候可能存在更小值满足 r = mid , mid不满足的时候
l += 1
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution: defminimizeSet(self, divisor1: int, divisor2: int, uniqueCnt1: int, uniqueCnt2: int) -> int: lcm_ = math.lcm(divisor1, divisor2) l = 0 r = 1 + max(divisor1, divisor2) * (uniqueCnt1 + uniqueCnt2) while l < r: mid = l + (r-l) // 2 check = (mid - mid // divisor1) < uniqueCnt1 or (mid - mid // divisor2) < uniqueCnt2 or (mid - mid // lcm_) < uniqueCnt1 + uniqueCnt2 if check: l = mid + 1 else: r = mid return l
410. Split Array Largest Sum
Given an integer array nums and an integer
k, split nums into k non-empty
subarrays such that the largest sum of any subarray is
minimized.
Return the minimized largest sum of the split.
A subarray is a contiguous part of the array.
1 2 3 4 5 6 7 8 9 10 11
Example 1: Input: nums = [7,2,5,10,8], k = 2 Output: 18 Explanation: There are four ways to split nums into two subarrays. The best way is to split it into [7,2,5] and [10,8], where the largest sum among the two subarrays is only 18.
Example 2: Input: nums = [1,2,3,4,5], k = 2 Output: 9 Explanation: There are four ways to split nums into two subarrays. The best way is to split it into [1,2,3] and [4,5], where the largest sum among the two subarrays is only 9.
classSolution: defsplitArray(self, nums: List[int], m: int) -> int: n = len(nums) f = [[10**18] * (m + 1) for _ inrange(n + 1)] sub = [0] for elem in nums: sub.append(sub[-1] + elem) f[0][0] = 0 for i inrange(1, n + 1): for j inrange(1, min(i, m) + 1): for k inrange(i): f[i][j] = min(f[i][j], max(f[k][j - 1], sub[i] - sub[k])) return f[n][m]
classSolution: defsplitArray(self, nums: List[int], k: int) -> int: defcheck(target): count = 0 sum_ = 0 for i in nums: if sum_ + i <= target: sum_ += i else: count += 1 sum_ = i return count+1 > k l = max(nums) r = sum(nums) while l < r: mid = l + (r-l) // 2 if check(mid): l = mid + 1 else: r = mid return r