278. 第一个错误的版本
# The isBadVersion API is already defined for you.
# @param version, an integer
# @return a bool
# def isBadVersion(version):
class Solution:
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
l,r=1,n
while l<r:
mid=l+(r-l)//2
if not isBadVersion(mid):
l=mid+1
else:
r=mid
return l
34. 在排序数组中查找元素的第一个和最后一个位置
二分查找的左右边界
左右边界都闭合
二分查找最关键的是如果左右边界取错的情况下容易出现死循环,此时在左右边界都取的情况下避免死循环的处理在于每一次左右边界都要发生改变
def searchleftRange(self,nums: List[int],target: int) ->int:
lefts,rights = 0,len(nums)-1
while lefts <= rights:
#因为lefts <= rights,所以每次搜索的区间为[lefts,rights]
mid = (lefts+rights)//2
if nums[mid] > target:
rights = mid-1
#右侧必须进行回缩,否则在左右区间都取到的情况下可能会发生死循环的现象,
#比如如果这一句改为了rights = mid,
#此时如果lefts = 0,rights = 1的情况下mid = (0+1)/2 = 0,
#如果nums[mid] > target,此时就会无限循环
#出现lefts = 0,rights = 0的情况时,此时mid = (lefts+rights)/2 = 0,
elif nums[mid] < target:
lefts = mid+1
#同理左侧也必须进行回缩
elif nums[mid] == target:
rights = mid-1
#同理相等的时候也必须进行回缩,否则会发生死循环,
#但此时nums[mid] == target,rights边界向右移动了,
#所以就会漏掉mid这一区间与target相等的现象
if rights+1 < len(nums) and nums[rights+1] == target:
#跳出循环时单独考虑漏掉的这一种情况
#因为nums[mid] == target之时,rights = mid-1进行区间放缩,
#区间内漏掉了相等的数值nums[mid],
#此时rights = mid-1,mid = rights+1,所以此时返回rights+1
return rights+1
else:
return -1
作者:zuo-ni-ai-chi-de-tang-seng-rou
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/li-kou-34ti-xiao-bai-du-neng-kan-dong-de-fang-fa-m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
if len(nums)==0:
return [-1,-1]
left=self.searchleftRange(nums,target)
right=self.searchrightRange(nums,target)
return [left,right]
def searchleftRange(self,nums,target):
l,r=0,len(nums)-1
while l<=r:
mid=l+(r-l)//2
if nums[mid]<target:
l=mid+1
else:
r=mid-1
if r+1<len(nums) and nums[r+1]==target:
return r+1
else:
return -1
def searchrightRange(self,nums,target):
l,r=0,len(nums)-1
while l<=r:
mid=l+(r-l)//2
if nums[mid]<=target:
l=mid+1
else:
r=mid-1
if l-1>=0 and nums[l-1]==target:
return l-1
else:
return -1
1266. 访问所有点的最小时间
class Solution:
def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
x0,y0=points[0]
res=0
for i in range(1,len(points)):
x1,y1=points[i]
res+=max(abs(x1-x0),abs(y1-y0))
x0,y0=x1,y1
return res
149. 直线上最多的点数
我们对所有点遍历,记录包含这个点在内的所有直线中,能组成的点数最多的直线的点数数量,返回这些数量的最大值
我们对一个点遍历的时候,再遍历所有点
维护两个变量
一个来记录和这个点相同的点(重复点)
一个来记录非重复点和这个点组成的各个直线以及它们拥有的点数
即使用哈希表,键为dx/dy,值是这个直线拥有的点数。这里使用 Counter 直接统计各个直线拥有的点数。
返回最多拥有点数的直线所拥有的点数与重复点之和。
from collections import Counter
from decimal import Decimal
class Solution:
def maxPoints(self, points: List[List[int]]) -> int:
#Decimal:增加浮点数的境地
def K(i,j):
return float('Inf') if i[1] - j[1] == 0 else Decimal(i[0] - j[0]) / Decimal(i[1] - j[1])
if len(points) <= 2:
return len(points)
maxans = 0
for i in points:
# 相同点的个数
same = sum(1 for j in points if j == i)
hashmap = Counter([K(i,j) for j in points if j != i])
tempmax = hashmap.most_common(1)[0][1] if hashmap else 0
maxans = max(same + tempmax, maxans)
return maxans
593. 有效的正方形
边长相等,对角线长度相等
class Solution:
def validSquare(self, p1: List[int], p2: List[int], p3: List[int], p4: List[int]) -> bool:
def distance(x,y):
return (y[1]-x[1])**2+(y[0]-x[0])**2
arr=[p1,p2,p3,p4]
arr=sorted(arr,key=lambda x:(x[0],x[1]))
if distance(arr[0],arr[1])!=0 and distance(arr[0],arr[1])==distance(arr[3],arr[1]) and distance(arr[0],arr[3])==distance(arr[2],arr[1]) and distance(arr[1],arr[3])==distance(arr[2],arr[3]):
return True
return False
65. 有效数字
首先是符号位,表示这个数是正数还是负数。题目当中没有明说,但是我们可以猜测出来,正数用正号表示也是合法的。第二个部分是科学记数法的前半部分,它可以是一个小数。第三个部分是e,即科学记数法当中的e。最后一个部分是整数部分,表示e的指数
class Solution:
def isNumber(self, s: str) -> bool:
s=s.strip()
number=[str(i) for i in range(10)]
num_up,num_after,e_up,dot_up=False,False,False,False
for i in range(len(s)):
c=s[i]
if c in number:
num_up=True
num_after=True
elif c in ('+','-'):
if i>0 and s[i-1]!='e':
return False
elif c=='.':
if e_up or dot_up:
return False
dot_up=True
elif c=='e':
if e_up or not num_up:
return False
e_up=True
num_up=False
else:
return False
return num_up and num_after
正则表达式匹配:
import re
class Solution:
def isNumber(self, s: str) -> bool:
pat=re.compile(r'^[+-]?(\d+\.\d+|\.\d+|\d+\.|\d+)(e[+-]?\d+)?$')
#去掉首尾空格
if len(re.findall(pat,s.strip())):
return True
else:
return False
836. 矩形重叠
没有重叠的情况:
矩形 rec1 在矩形 rec2 的左侧; rec1[2] <= rec2[0]
矩形 rec1 在矩形 rec2 的右侧;rec1[0] >= rec2[2]
矩形 rec1 在矩形 rec2 的上方;rec1[1] >= rec2[3]
矩形 rec1 在矩形 rec2 的下方; rec1[3] <= rec2[1]
class Solution(object):
def isRectangleOverlap(self, rec1, rec2):
return not (rec1[2] <= rec2[0] or # left
rec1[3] <= rec2[1] or # bottom
rec1[0] >= rec2[2] or # right
rec1[1] >= rec2[3]) # top
法二:检查区域
矩形重叠说明 投影到x,y轴上的线段有重叠,说明 min(rec2[2],rec1[2])>max(rec2[0],rec1[0])
min(rec2[3],rec1[3])>max(rec2[1],rec1[1])
class Solution:
def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool:
return min(rec2[2],rec1[2])>max(rec2[0],rec1[0]) and min(rec2[3],rec1[3])>max(rec2[1],rec1[1])
223. 矩形面积
没有重叠的情况:
重叠区域:
上边界,取两个矩形的上边界的最小值
下边界,取两个矩形的下边界的最大值
左边界,取两个矩形的左边界的最大值
右边界,取两个矩形的右边界的最小值
class Solution:
def computeArea(self, A: int, B: int, C: int, D: int, E: int, F: int, G: int, H: int) -> int:
#将靠左的挪到前面
if A>E:
return self.computeArea(E,F,G,H,A,B,C,D)
#如果没有重叠
if B>=H or D<=F or E>=C:
return abs(C-A)*abs(D-B)+abs(G-E)*abs(H-F)
up=min(D,H)
down=max(B,F)
left=max(A,E)
right=min(C,G)
return abs(C-A)*abs(D-B)+abs(G-E)*abs(H-F)-abs(up-down)*abs(right-left)
883. 三维形体投影面积
从顶部看是 网格中非零值的数目
从侧面看,由该形状生成的阴影将是网格中每一行的最大值。
从前面看,由该形状生成的阴影将是网格中每一列的最大值。
class Solution:
def projectionArea(self, grid: List[List[int]]) -> int:
res=0
for i in range(len(grid)):
max_h=0
max_l=0
for j in range(len(grid)):
if grid[i][j]!=0:
res+=1
#从侧面看,i不变时的最大值
max_l=max(max_l,grid[i][j])
#从正面看,j不变时的最大值
max_h=max(max_h,grid[j][i])
res+=max_h+max_l
return res
面试题 16.14. 最佳直线
用一个字典保存已找到的所有直线的出现次数,和其穿过的下标最小的两个点的下标
遍历所有点对,更新字典及最优解
class Solution:
def bestLine(self, points: List[List[int]]) -> List[int]:
d = {}
x = y = 0
maxCount = 0
for i in range(len(points)):
for j in range(i+1, len(points)):
k, b = self.f([points[i], points[j]])
if (k, b) in d.keys():
d[(k, b)][0] += 1
else:
d[(k, b)] = [1, (i, j)]
if d[(k, b)][0] > maxCount or (d[(k, b)][0] == maxCount and d[(k, b)][1][0] < x) or (d[(k, b)][0] == maxCount and d[(k, b)][1][1] < y):
maxCount = d[(k, b)][0]
x, y = d[(k, b)][1]
print(x, y)
return [x, y]
# 求两点之间连线的k和b
def f(self, points: List[List[int]]) -> List[int]:
if points[0][0] == points[1][0]:
return [float('inf'), points[0][0]]
else:
return [(points[1][1]-points[0][1]) / (points[1][0]-points[0][0]),
(points[0][1]*points[1][0]-points[1][1]*points[0][0]) / (points[1][0]-points[0][0])]