标准的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
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
好像是当初算法期末考里面的一题, 现在又不懂了。
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
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