- 本文整理了Lintcode二分法题目的coding练习,参考了九章算法课程的配套习题,题目顺序由易到难,非常典型。算法入门的同学可以按照这个题目顺序进行练习。
- 代码都是用python实现,基本上是参考了九章用的解法,如果发现有错误或者不理解的地方,可以留言告诉我。
- 体会:二分法题目基本就是找满足某个条件的first position或者last position问题。怎么将题目转化成这种问题就是考验是否聪明了,勤能补拙,不够聪明的话,多练习,见多识广也行。
- 目前在持续更新中
457. 经典二分查找问题
在一个排序数组中找一个数,返回该数出现的任意位置,如果不存在,返回 -1
class Solution:
"""
@param nums: An integer array sorted in ascending order
@param target: An integer
@return: An integer
"""
def findPosition(self, nums, target):
# write your code here
# 二分查找问题最简单的形式,不必考虑first postion还是last position了
if len(nums) == 0:
return -1
start = 0
end = len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if nums[mid] == target:
return mid # 体会这里和14题的区别
if nums[mid] > target:
end = mid
if nums[mid] < target:
start = mid
if nums[start] == target:
return start
if nums[end] == target:
return end
return -1
二刷
题目很简单,和一刷时代码一样
三刷,经典的二分题目,要背住模板
- 先判断异常情况,即数组为空
- while 循环条件是start + 1 < end:
- start, end初始化是0, n - 1
- 对于其它题目,再留意一下是要first position 还是last position
14. 二分查找
给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1。
class Solution:
"""
@param nums: The integer array.
@param target: Target to find.
@return: The first position of target. Position starts from 0.
"""
def binarySearch(self, nums, target):
# write your code here
# 典型的二分查找题目,应该是最简单的了
# first positon
start = 0
end = len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if nums[mid] == target:
end = mid
if nums[mid] > target:
end = mid
if nums[mid] < target:
start = mid
if nums[start] == target:
return start
if nums[end] == target:
return end
return -1
二刷
典型的二分查找题目,注意是要target第一次出现的下标。二刷代码和一刷的没什么不同。加深了对二分法题目的理解。
三刷,典型题目,再熟悉一下模板
141. 对x开根
实现 int sqrt(int x) 函数,计算并返回 x 的平方根。
class Solution:
"""
@param x: An integer
@return: The sqrt of x
"""
def sqrt(self, x):
# write your code here
# 要灵活运用二分法,看这个题目怎么转化成二分查找的思路
# 寻找最后一个数y使得y * y <= x
# last position问题
start = 0
end = x
while start + 1 < end:
mid = start + (end - start) // 2
if mid * mid == x:
return mid
if mid * mid > x:
end = mid
if mid * mid < x:
start = mid
if end * end <= x:
return end
if start * start <= x:
return start
二刷
def sqrt(self, x):
# write your code here
# 这是二刷了
# 这个题目就不是那么典型的二分了,思路不是那么直接
# x的平方根肯定是在0和x之间,所以在0-x之间二分,不断缩小范围找到square root
# 找到最大的square root,使得square root * square root <= x
# last position问题
if x < 0:
return -1
start = 0
end = x
while start + 1 < end:
mid = start + (end - start) // 2
if mid * mid == x:
return mid
if mid * mid < x:
start = mid
if mid * mid > x:
end = mid
if end * end <= x:
return end
if start * start <= x:
return start
return -1
三刷,最后的判断那里不是很熟练
力扣240. 搜索二维矩阵 II
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
m, n = len(matrix), len(matrix[0])
# for i in range(m):
# for j in range(n):
# if matrix[i][j] == target:
# return True
for i in range(m):
if self.searchNums(matrix[i], target):
return True
return False
def searchNums(self, nums, target):
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if nums[mid] == target:
return True
elif nums[mid] > target:
end = mid
else:
start = mid
if nums[start] == target or nums[end] == target:
return True
return False
二刷,和一刷解法一样,没有充分利用该矩阵的性质
28. 搜索二维矩阵
写出一个高效的算法来搜索 m × n矩阵中的值。
这个矩阵具有以下特性:
每行中的整数从左到右是排序的。
每行的第一个数大于上一行的最后一个整数。
class Solution:
"""
@param matrix: matrix, a list of lists of integers
@param target: An integer
@return: a boolean, indicate whether matrix contains target
"""
def searchMatrix(self, matrix, target):
# write your code here
# 这个二位矩阵是递增的,不知道是否有重复的数。不过当成first position来做就行
# 可以把二维矩阵转化成一维数组来做,这样就是自己熟悉的题目了
# m*n的二位矩阵,在一维数组中的index // n就是行数,index % n就是列数
m, n = len(matrix), len(matrix[0])
start = 0
end = m * n -1
while start + 1 < end:
mid = start + (end - start) // 2
if matrix[mid // n][mid % n] == target:
return True
if matrix[mid // n][mid % n] > target:
end = mid
if matrix[mid // n][mid % n] < target:
start = mid
if matrix[start // n][start % n] == target:
return True
if matrix[end // n][end % n] == target:
return True
return False
二刷,加深理解了怎么将二维数组转为以为数组
class Solution:
"""
@param matrix: matrix, a list of lists of integers
@param target: An integer
@return: a boolean, indicate whether matrix contains target
"""
def searchMatrix(self, matrix, target):
# write your code here
if len(matrix) == 0:
return False
m, n = len(matrix), len(matrix[0])
start, end = 0, m * n - 1
while start + 1 < end:
mid = start + (end - start) // 2
row = mid // n
col = mid % n
if matrix[row][col] == target:
return True
if matrix[row][col] < target:
start = mid
if matrix[row][col] > target:
end = mid
if matrix[start // n][start % n] == target:
return True
if matrix[end // n][end % n] == target:
return True
return False
61. 搜索区间
给定一个包含 n 个整数的排序数组,找出给定目标值 target 的起始和结束位置。
如果目标值不在数组中,则返回[-1, -1]
class Solution:
"""
@param A: an integer sorted array
@param target: an integer to be inserted
@return: a list of length 2, [index1, index2]
"""
def searchRange(self, A, target):
# write your code here
# 起始位置是first position,结束位置是last position
# 这是一个排序数组,可能有重复数字
# 可以简化成先找first position当成左边界,再找last position当成右边界
start = 0
end = len(A) - 1
# 什么时候要考虑数组为空,什么时候不考虑呢??
if A == []:
return [-1, -1]
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] == target:
end = mid
if A[mid] > target:
end = mid
if A[mid] < target:
start = mid
if A[start] == target:
leftbound = start
elif A[end] == target:
leftbound = end
else:
return [-1, -1]
start = leftbound
end = len(A) - 1 # 这里也要重新对end赋值
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] == target:
start = mid
if A[mid] > target:
end = mid
if A[mid] < target:
start = mid
if A[end] == target:
rightbound = end
elif A[start] == target:
rightbound = start
return [leftbound, rightbound]
二刷,基本掌握
458. 目标最后位置
给一个升序数组,找到 target 最后一次出现的位置,如果没出现过返回 -1
样例 1:
输入:nums = [1,2,2,4,5,5], target = 2
输出:2
样例 2:
输入:nums = [1,2,2,4,5,5], target = 6
输出:-1
class Solution:
"""
@param nums: An integer array sorted in ascending order
@param target: An integer
@return: An integer
"""
def lastPosition(self, nums, target):
# write your code here
# last position问题,升序数组,可能有重复
start = 0
end = len(nums) - 1
if nums == None or len(nums) == 0:
return -1
while start + 1 < end:
mid = start + (end - start) // 2
# last position问题,先缩小范围
if nums[mid] <= target:
start = mid
else:
end = mid
# 先判断end,等于target的话,返回索引。
if nums[end] == target:
return end
if nums[start] == target:
return start
return -1
二刷
典型的last position问题,心里思考了一下,和一刷的思路和代码基本一样。
585. 山脉序列中的最大值
给 n 个整数的山脉数组,即先增后减的序列,找到山顶(最大值)
例1:
输入: nums = [1, 2, 4, 8, 6, 3]
输出: 8
例2:
输入: nums = [10, 9, 8, 7],
输出: 10
注意事项
数组严格递增,严格递减
class Solution:
"""
@param nums: a mountain sequence which increase firstly and then decrease
@return: then mountain top
"""
def mountainSequence(self, nums):
# write your code here
# 不是first/last position问题了,通过二分逐步缩小范围
# 长度应该是默认大于等于3的
start = 0
end = len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
# nums[mid]恰好是最大的情况
if nums[mid] > nums[mid-1] and nums[mid] > nums[mid+1]:
return nums[mid]
# nums[mid]是左边最大的情况
elif nums[mid] > nums[mid-1] and nums[mid] < nums[mid+1]:
start = mid
# nums[mid]是右边最大的情况
elif nums[mid] > nums[mid+1] and nums[mid] < nums[mid-1]:
end = mid
# 考虑只有递增或者只有递减的情况
if nums[start] > nums[end]:
return nums[start]
else:
return nums[end]
二刷
忘记了一刷时的思路,自己独立想出来的,和一刷时的基本一样,但是更清晰了。
def mountainSequence(self, nums):
# write your code here
# 这是二刷,可以用遍历整个数组来找到最大值,
# 但是用二分法怎么做呢?
# 思考题目,山顶的特点是比左边的值大,也比右边的值大
# 如果找到mid,满足这个特点,那么就是山顶了
if len(nums) == 0 or nums == None:
return None
start = 0
end = len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
# mid恰好是山峰的情况
if nums[mid] >= nums[mid + 1] and nums[mid] >= nums[mid - 1]:
return nums[mid]
# mid在左边山坡的情况
if nums[mid] >= nums[mid - 1] and nums[mid] <= nums[mid + 1]:
start = mid
# mid在右边山坡的情况
if nums[mid] <= nums[mid - 1] and nums[mid] >= nums[mid + 1]:
end = mid
if nums[start] > nums[end]:
return nums[start]
else:
return nums[end]
三刷,代码更简洁了
class Solution:
"""
@param nums: a mountain sequence which increase firstly and then decrease
@return: then mountain top
"""
def mountainSequence(self, nums):
# write your code here
start, end = 0, len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if nums[mid] < nums[mid + 1]:
start = mid
else:
end = mid
return nums[start] if nums[start] > nums[end] else nums[end]
460. 在排序数组中找最接近的K个数
给一个目标数 target, 一个非负整数 k, 一个按照升序排列的数组 A。在A中找与target最接近的k个整数。返回这k个数并按照与target的接近程度从小到大排序,如果接近程度相当,那么小的数排在前面。
样例 1:
输入: A = [1, 2, 3], target = 2, k = 3
输出: [2, 1, 3]
样例 2:
输入: A = [1, 4, 6, 8], target = 3, k = 3
输出: [4, 1, 6]
class Solution:
"""
@param A: an integer array
@param target: An integer
@param k: An integer
@return: an integer array
"""
def kClosestNumbers(self, A, target, k):
# write your code here
# 自己想是没有想出来,看了答案以后觉得也很简单。
# 采用二分法加双指针,用二分法确定一个位置,左边是<target的,右边是>=target的
# 然后用两根指针从这个位置向两边走,依次找到最接近的K个数
# 找到最接近target的两个数,A[right] >= target,A[left] < target
right = self.findUpperClosest(A, target)
left = right - 1
# 两根指针从中间向两边走,依次找到最接近的K个数
res = []
for _ in range(k):
if self.isLeftCloser(A, target, left, right):
res.append(A[left])
left = left - 1
else:
res.append(A[right])
right = right + 1
return res
# 找到>=target的第一个数的位置,first position
def findUpperClosest(self, A, target):
start = 0
end = len(A) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] >= target:
end = mid
else:
start = mid
if A[start] >= target:
return start
if A[end] >= target:
return end
# 找不到的情况,即target比A中的任何数都大。
return len(A)
def isLeftCloser(self, A, target, left, right):
if left < 0:
return False
if right >= len(A):
return True
return target - A[left] <= A[right] - target
二刷
二刷的时候完全没有思路,感觉很难。最后自己静静心,认真分析题目的条件,把问题拆解开,一步一步做出来了,好开心。
def kClosestNumbers(self, A, target, k):
# write your code here
# 这是二刷了
# 二刷的时候,简单的题目基本都没有问题,
# 中等难度的题目,有的思考一下可以做出来,非常有成就感
# 有的完全没有思路,想了半天也不行,还得看答案,非常有挫败感
# 这个题目可能是属于后者,怕怕。。。
# 审题,思考。先用二分法找到与target最接近的那个数
# 然后依次比较其左边和右边的数,看哪个更接近target
# 最后经过自己的思考,独立做出来了。好开心!!!
# 而且感觉我的思路比答案的更清晰
if len(A) == 0 or A == None:
return None
if k == 0:
return []
index = self.closestNumber(A, target)
left = index - 1
right = index + 1
res = [A[index]]
for i in range(k - 1):
if left >= 0 and right <= len(A) - 1:
if abs(A[left] - target) <= abs(A[right] - target):
res.append(A[left])
left -= 1
else:
res.append(A[right])
right += 1
elif left < 0 and right <= len(A) - 1:
res.append(A[right])
right += 1
elif left >= 0 and right > len(A) - 1:
res.append(A[left])
left -= 1
return res
def closestNumber(self, A, target):
# 注意要的是first position
start = 0
end = len(A) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] == target:
return mid
if A[mid] > target:
end = mid
if A[mid] < target:
start = mid
if abs(A[start] - target) <= abs(A[end] - target):
return start
else:
return end
三刷,时间复杂度是O(n),空间复杂度是O(n)
class Solution:
"""
@param A: an integer array
@param target: An integer
@param k: An integer
@return: an integer array
"""
def kClosestNumbers(self, A, target, k):
# write your code here
tmp = []
for index, item in enumerate(A):
tmp.append((abs(item - target), index))
tmp.sort()
res = []
for i in range(k):
index = tmp[i][1]
res.append(A[index])
return res
没有想出来二分法这个方法,看了答案后也可以理解,思路也非常好,时间复杂度是O(logn),空间复杂度是O(1)。自己尝试做一做。
class Solution:
"""
@param A: an integer array
@param target: An integer
@param k: An integer
@return: an integer array
"""
def kClosestNumbers(self, A, target, k):
# write your code here
# 用二分法找到最接近的那一个数
# 然后从这个数分别向两边移动,依次找到次接近的数
if len(A) == 0:
return []
if len(A) < k:
return []
if k == 0:
return []
index = self.closestNumber(A, target)
res = [A[index]]
k = k - 1
left = index - 1
right = index + 1
# for _ in range(k - 1):
while left >= 0 and right <= len(A) - 1 and k > 0:
if abs(A[left] - target) <= abs(A[right] - target):
res.append(A[left])
left -= 1
k -= 1
else:
res.append(A[right])
right += 1
k -= 1
while k > 0 and left >= 0:
res.append(A[left])
left -= 1
k -= 1
while k > 0 and right <= len(A) - 1:
res.append(A[right])
right += 1
k -= 1
return res
def closestNumber(self, A, target):
if len(A) == 0:
return None
start, end = 0, len(A) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] == target:
end = mid
elif A[mid] < target:
start = mid
else:
end = mid
if abs(A[start] - target) <= abs(A[end] - target):
return start
return end
428. x的n次幂
实现 pow(x, n). (n是一个整数)
样例 1:
输入: x = 9.88023, n = 3
输出: 964.498
样例 2:
输入: x = 2.1, n = 3
输出: 9.261
样例 3:
输入: x = 1, n = 0
输出: 1
class Solution:
"""
@param x {float}: the base number
@param n {int}: the power number
@return {float}: the result
"""
def myPow(self, x, n):
# write your code here
# 注意考虑n为负数的情况。如果n为负数,令x = 1/x,n = -n
if n < 0:
x = 1 / x
n = -n
ans = 1
tmp = x
while n != 0:
if n % 2 == 1:
ans = ans * tmp
tmp = tmp * tmp
n = n // 2
return ans
二刷
先是尝试暴力法,即依次进行n个x相乘,时间复杂度是O(n),这样是会超时的。
然后将问题转化为x的m次幂和x的n次幂,并且记住已经计算过的答案,不用再次计算。这样可以通过。
不过这都没有一刷的解法好。
class Solution:
"""
@param x {float}: the base number
@param n {int}: the power number
@return {float}: the result
"""
def myPow(self, x, n):
# write your code here
# if n == 0:
# return 1
# if n > 0:
# tmp = 1
# for _ in range(n):
# tmp = tmp * x
# return tmp
# if n < 0:
# n = -n
# tmp = 1
# for _ in range(n):
# tmp = tmp * x
# return 1 / tmp
memo = {}
return self.help(x, n, memo)
def help(self, x, n, memo):
if n == 0:
return 1
if n == 1:
return x
if n in memo:
return memo[n]
if n > 0:
left = n // 2
right = n - left
res = self.help(x, left, memo) * self.help(x, right, memo)
memo[n] = res
return res
if n < 0:
n = -n
return 1 / self.help(x, n, memo)
159. 寻找旋转排序数组中的最小值
假设一个排好序的数组在其某一未知点发生了旋转(比如0 1 2 4 5 6 7 可能变成4 5 6 7 0 1 2)。你需要找到其中最小的元素。
样例 1:
输入:[4, 5, 6, 7, 0, 1, 2]
输出:0
解释:
数组中的最小值为0
样例 2:
输入:[2,1]
输出:1
解释:
数组中的最小值为1
注意事项:你可以假设数组中不存在重复元素。
class Solution:
"""
@param nums: a rotated sorted array
@return: the minimum number in the array
"""
def findMin(self, nums):
# write your code here
# 题目也没写啥是旋转数组,自己瞎理解了好久。。。
# 看到leetcode上的定义:
# 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转
# 根据定义可以得出旋转后的数组先升序,然后是一个最小值,再继续升序
# 理解到这一步,最小值左边的数都比它大,右边的数也都比它大
start = 0
end = len(nums) - 1
# 居然有不发生旋转的情况,题目都说了是旋转数组,我也是醉了。
# 判断是否进行了旋转,如果进行了旋转再进行while循环
if nums[start] > nums[end]:
while start + 1 < end:
mid = start + (end - start) // 2
if nums[mid] > nums[end]:
start = mid
if nums[mid] < nums[end]:
end = mid
if nums[start] < nums[end]:
return nums[start]
if nums[start] > nums[end]:
return nums[end]
二刷,掌握得不好,没有充分理解旋转数组的形状
75. 寻找峰值
给出一个整数数组(size为n),其具有以下特点:
相邻位置的数字是不同的
A[0] < A[1] 并且 A[n - 2] > A[n - 1]
假定P是峰值的位置则满足A[P] > A[P-1]且A[P] > A[P+1],返回数组中任意一个峰值的位置。
样例 1:
输入: [1, 2, 1, 3, 4, 5, 7, 6]
输出: 1 or 6
解释:
返回峰顶元素的下标
样例 2:
输入: [1,2,3,4,1]
输出: 3
注意事项
数组保证至少存在一个峰
如果数组存在多个峰,返回其中任意一个就行
数组至少包含 3 个数
class Solution:
"""
@param A: An integers array.
@return: return any of peek positions.
"""
def findPeak(self, A):
# write your code here
# 和LeetCode上的题目描述一对比,这个啰嗦极了。
# 下面这句话似乎也是错的,理解不了。。。
# A[0] < A[1] 并且 A[n - 2] > A[n - 1]
# 峰值元素比它左边的数大,也比它右边的数大。至少存在一个峰值元素。
# 理解到这一层的话,只要沿着一个上升的线找,就一定可找到峰值
# 计算中间位置mid,并比较A[mid]和A[mid+1]的值,
# 如果A[mid]大,说明左侧有峰值,end=mid
start = 0
end = len(A) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] > A[mid+1]:
end = mid
if A[mid] < A[mid+1]:
start = mid
return end
二刷,不如一刷代码简洁
class Solution:
"""
@param A: An integers array.
@return: return any of peek positions.
"""
def findPeak(self, A):
# write your code here
# 用二分来实现,时间复杂度低
if len(A) < 3:
return -1
start, end = 0, len(A) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] > A[mid - 1] and A[mid] > A[mid + 1]:
return mid
elif A[mid] > A[mid - 1]:
start = mid
else:
end = mid
if A[start] > A[start + 1] and A[start] > A[start - 1]:
return start
elif A[end] > A[end + 1] and A[end] > A[end - 1]:
return end
return -1
74. 第一个错误的代码版本
代码库的版本号是从 1 到 n 的整数。某一天,有人提交了错误版本的代码,因此造成自身及之后版本的代码在单元测试中均出错。请找出第一个错误的版本号。
#class SVNRepo:
# @classmethod
# def isBadVersion(cls, id)
# # Run unit tests to check whether verison `id` is a bad version
# # return true if unit tests passed else false.
# You can use SVNRepo.isBadVersion(10) to check whether version 10 is a
# bad version.
class Solution:
"""
@param n: An integer
@return: An integer which is the first bad version.
"""
def findFirstBadVersion(self, n):
# write your code here
start = 1
end = n
while start + 1 < end:
mid = start + (end - start) // 2
if SVNRepo.isBadVersion(mid):
end = mid
else:
start = mid
if SVNRepo.isBadVersion(start):
return start
if SVNRepo.isBadVersion(end):
return end
62. 搜索旋转排序数组
假设有一个排序的按未知的旋转轴旋转的数组(比如,0 1 2 4 5 6 7 可能成为4 5 6 7 0 1 2)。给定一个目标值进行搜索,如果在数组中找到目标值返回数组中的索引位置,否则返回-1。你可以假设数组中不存在重复的元素。
class Solution:
"""
@param A: an integer rotated sorted array
@param target: an integer to be searched
@return: an integer
"""
def search(self, A, target):
# write your code here
# 我本来考虑先找到最小值的位置,然后判断target在最小值左边还是右边,
# 然后在从二分法来搜索target,但是觉得这样太麻烦了,不是一个好办法
# 看了答案以后,发现九章给的方法也是这样
# 体会是:做事情先完成再完美,有解决方案比没有强
# 不要有洁癖,先完成再说
if not A:
return -1
min, minIdx = self.findMin(A)
if A[minIdx] <= target <= A[-1]:
return self.binarySearch(A, minIdx, len(A)-1, target)
return self.binarySearch(A, 0, minIdx-1, target)
def binarySearch(self, A, start, end, target):
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] > target:
end = mid
if A[mid] < target:
start = mid
if A[mid] == target:
return mid
if A[start] == target:
return start
if A[end] == target:
return end
return -1
def findMin(self, A):
# A是一个旋转排序数组,找到里面的最小值,返回这个值和索引
# 这和之前的159题目类似,题目顺序设置的真是好呀
start = 0
end = len(A) - 1
# 先判断数组是否旋转了,不旋转的话第一个数就是最小值
if A[start] > A[end]:
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] > A[start]:
start = mid
if A[mid] < A[end]:
end = mid
if A[start] < A[end]:
return A[start], start
return A[end], end
160. 寻找旋转排序数组中的最小值 II
假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2)。你需要找到其中最小的元素。
Example 1:
Input :[2,1]
Output : 1.
Example 2:
Input :[4,4,5,6,7,0,1,2]
Output : 0.
注意事项:该数组可能包含重复项。
class Solution:
"""
@param nums: a rotated sorted array
@return: the minimum number in the array
"""
def findMin(self, nums):
# write your code here
# 刚刚做了这个类似的题目,不同点是没有重复项。
# 这个题目说可能存在重复项,会有哪些影响呢?
# 不太清楚,按照二分的思路先做做看
# 这个题目的难点在于想到最坏的情况[1, 1, 1, 1, 1, 1, 1, 1, 0, 1]类似这样
start = 0
end = len(nums) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if nums[mid] == nums[end]:
end = end - 1 # 两个相等,去掉最后一个数,也不妨碍找到最小值
if nums[mid] > nums[end]:
start = mid
if nums[mid] < nums[end]:
end = mid
if nums[start] <= nums[end]:
return nums[start]
else:
return nums[end]
class Solution:
"""
@param nums: a rotated sorted array
@return: the minimum number in the array
"""
def findMin(self, nums):
# write your code here
# 题目也没说要O(logn)
# 其实不妨就直接用O(n)的方法来解决,不要有方法洁癖
min = nums[0]
for item in nums:
if item < min:
min = item
return min
63. 搜索旋转排序数组 II
跟进“搜索旋转排序数组”,假如有重复元素又将如何?
是否会影响运行时间复杂度?
如何影响?
为何会影响?
写出一个函数判断给定的目标值是否出现在数组中。
例1:
输入:
[]
1
输出:
false
例2:
输入:
[3,4,4,5,7,0,1,2]
4
输出:
true
class Solution:
"""
@param A: an integer ratated sorted array and duplicates are allowed
@param target: An integer
@return: a boolean
"""
def search(self, A, target):
# write your code here
# 如果没有重复元素的话,可以用两个二分法来实现
# 现在这种情况,不如直接for循环吧,O(n)的时间复杂度
# 但是这个方法估计不能让面试官满意。。。
for item in A:
if item == target:
return True
return False