1.二分查找-I
借助了两个指针left和right,取中间的值就可以
class Solution:
def search(self , nums: List[int], target: int) -> int:
# write code here
left,right=0,len(nums)-1
while left<=right:
x=(right-left)//2+left
if nums[x]==target:
return x
elif nums[x]<target:
left+=1
elif nums[x]>target:
right-=1
return -1
2.二分查找-II(有重复数字)
这个其实只添加了判断是第一次出现的while语句,加了两行代码
class Solution:
def search(self , nums: List[int], target: int) -> int:
# write code here
left,right=0,len(nums)-1
while left<=right:
x=(right-left)//2+left
if nums[x]==target:
# 保证找到的target是第一次出现
while x > 0 and nums[x-1] == nums[x]:
x-=1
return x
elif nums[x]<target:
left+=1
elif nums[x]>target:
right-=1
return -1
3.二维数组中的查找
一个偷懒的简单方法
class Solution:
def Find(self , target: int, array: List[List[int]]) -> bool:
# write code here
for i in array:
if target in i:
return True
return False
这道题其实和上面是一样的,我们也是用二分来做,但是可以看做是一个二维的二分,因为右下是增大,所以我们要从左下或者右上开始,才能比较好的进行比较。一个控制上下,一个控制左右,并且要一个增一个减,所以需要注意一下开始的起点。
class Solution:
def Find(self , target: int, array: List[List[int]]) -> bool:
# 从左下或者右上开始找 因为i和j得一个增一个减 如果左上或右下就不好找了
# write code here
n,m=len(array),len(array[0])
i=0
j=m-1
if n*m==0:
return False
while i<n and j>=0:
if target == array[i][j]:
return True
elif target > array[i][j]:
i+=1
elif target < array[i][j]:
j-=1
return False
4.寻找峰值
爬坡的过程中一定会遇到最大值,同样的,如果找波谷就是找下坡路的最小值
class Solution:
def findPeakElement(self , nums: List[int]) -> int:
start,end = 0,len(nums)-1
while start<end:# 这里其实就是在找最大值
mid = (start+end)//2
right = mid + 1
if nums[mid] >= nums[right]:
end = mid
else:
start = mid+1
return start
5.数组中的逆序对
这个是视频讲的,直接挨着比,然后计数就可以了。找到比当前数小的,那么比当前数大的和该数都可以比现在这个小数大,所以是len+1。然后依次这么做下去,有一点点绕。
class Solution:
def InversePairs(self , data: List[int]) -> int:
# write code here
# 分为两个区间 左边找 右边找 直到全拆完 然后横跨两个区间的
# [1,2,3,4,5,6,7,0] 中有 1,0 2,0 3,0 ......
#下面这个方法很巧妙 他是直接挨着比 但是比这个小的 比他大的放一堆 比他小的放一堆
#找到比当前数小的 那么比当前数大的和该数都可以比现在这个小数大 所以是len+1
#然后再对两个新列表各自作比较
return self.recur(data)%1000000007
def recur(self,arr):
if len(arr) <= 1: return 0
b,s = [],[]
res,pre=0,arr[0]
for n in arr[1:]:
if n > pre:
b.append(n)
else:
s.append(n)
res += len(b) + 1
return res + self.recur(b) + self.recur(s)# 递归一下 找一下后面的东西 一个数一个数的比
6.旋转数组的最小数字
class Solution:
def minNumberInRotateArray(self , rotateArray: List[int]) -> int:
# write code here
if len(rotateArray)==0:
return 0
elif len(rotateArray)<=2:
return rotateArray[-1]
left,right=0,len(rotateArray)-1
while left<right:
mid=(left+right)//2
if rotateArray[left]<rotateArray[right]:
# 因为是旋转的,所以左边一般都是大于右边的 当左边小于右边了,就说明这就是那个极小值了
return rotateArray[left]
elif rotateArray[left]<rotateArray[mid]:
left=mid+1
elif rotateArray[right]>rotateArray[mid]:
right=mid
else :
left+=1
return rotateArray[right]
7.比较版本号
变成列表来做,一个一个的比,如果长度小了,就直接补0
class Solution:
def compare(self , version1: str, version2: str) -> int:
# write code here
nums1 = version1.split('.')
nums2 = version2.split('.')
n1, n2 = len(nums1), len(nums2)# 这个是按照.分开的,所以可以把0分开 直接int就可以让他变成一个整数了
# 满足条件就跳出 不满足就一直循环 直到结尾
for i in range(max(n1, n2)):
i1 = int(nums1[i]) if i < n1 else 0# 位数不够的时候直接添加0
i2 = int(nums2[i]) if i < n2 else 0
if i1 != i2:
return 1 if i1 > i2 else -1
return 0