文章目录
一、0704二分查找
题目链接
题目描述:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
思路:这道题很基础,直接按照二分查找的算法实现即可。
设定左右节点为数组两端,即:
l
e
f
t
=
0
,
r
i
g
h
t
=
l
e
n
(
n
u
m
s
)
−
1
left = 0,right = len(nums) - 1
left=0,right=len(nums)−1
分别代表待查找区间为:
[
l
e
f
t
,
r
i
g
h
t
]
(
左
闭
右
闭
)
。
[left, right](左闭右闭)。
[left,right](左闭右闭)。
取两个节点中心位置
m
i
d
mid
mid,先比较中心位置值
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid] 与目标值
t
a
r
g
e
t
target
target的大小。
如果中心位置值
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid]与目标值
t
a
r
g
e
t
target
target相等,则返回中心位置。
如果中心位置值
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid]小于目标值
t
a
r
g
e
t
target
target,则将左节点设置为
m
i
d
+
1
mid + 1
mid+1,然后继续在右区间
[
m
i
d
+
1
,
r
i
g
h
t
]
[mid + 1, right]
[mid+1,right]搜索。
如果中心位置值
n
u
m
s
[
m
i
d
]
nums[mid]
nums[mid]大于目标值
t
a
r
g
e
t
target
target,则将右节点设置为
m
i
d
−
1
mid - 1
mid−1,然后继续在左区间
[
l
e
f
t
,
m
i
d
−
1
]
[left, mid - 1]
[left,mid−1]搜索。
代码如下:
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)-1
while left <= right:
mid = (left+right)//2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid-1
else:
left = mid + 1
return -1
运行结果如下:
官方代码:
class Solution:
def search(self, nums: List[int], target: int) -> int:
low, high = 0, len(nums) - 1
while low <= high:
mid = (high - low) // 2 + low
num = nums[mid]
if num == target:
return mid
elif num > target:
high = mid - 1
else:
low = mid + 1
return -1
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-by-leetcode-solution-f0xw/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
感觉二分查找的思路就挺清晰的,实现出来大同小异。
观察可发现,在判断那里先赋值再做比较,可以减少一次nums索引的时间,加快执行用时。
二、Sqrt(x)
题目链接
题目描述:
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
示例:
输入:x = 4
输出:2
思路:这道题如果要用二分查找的思想来解决的话,可以将查找范围限定在
[
0
,
x
]
[0,x]
[0,x]之间,当
m
i
d
2
<
x
mid^2<x
mid2<x时,更新范围集合为
[
0
,
m
i
d
−
1
]
[0,mid-1]
[0,mid−1];当
m
i
d
2
>
x
mid^2>x
mid2>x时,更新范围集合为
[
m
i
d
+
1
,
x
]
[mid+1,x]
[mid+1,x]。
在计算的过程中,使用变量ans将目前满足条件的最大整数值保留下来。
代码如下:
class Solution:
def mySqrt(self, x: int) -> int:
left = 0
right = x
ans = -1
while left<=right:
mid = (left+right)//2
if mid**2 == x:
ans = mid
return ans
elif mid**2 < x:
ans = mid
left = mid+1
else:
right = mid-1
return ans
使用作弊代码,发现快了挺多:
class Solution:
def mySqrt(self, x: int) -> int:
import math
return int(math.sqrt(x))
使用牛顿迭代的方法:
class Solution:
def mySqrt(self, x: int) -> int:
val = x
error = x-0
while error >= 1:
last = val
val = (val+x/val)/2
error = abs(val-last)
return int(val)
官方提供的使用二分查找思想的代码如下:
class Solution:
def mySqrt(self, x: int) -> int:
l, r, ans = 0, x, -1
while l <= r:
mid = (l + r) // 2
if mid * mid <= x:
ans = mid
l = mid + 1
else:
r = mid - 1
return ans
很好奇为什么官方的快这么多,修改原代码,发现直接求幂运算比两个mid相乘慢,即mid**2改成mid*mid。修改后结果如下。
一种基于地址移位的快速sqrt算法