1.用牛顿迭代法求解 361800 的平方根,并推导牛顿迭代法的求解过程(即牛顿迭代法主要迭代公式的推导)。
求n的平方根可转化为方程 x 2 = n x^2=n x2=n的解,即 f ( x ) = x 2 − n = 0 f(x)=x^2-n=0 f(x)=x2−n=0的解
- 取 x = x 0 x=x_0 x=x0,判断 f ( x 0 ) f(x_0) f(x0)是否等于0或无限接近于0,如果不是则做过点 ( x 0 , f ( x 0 ) (x_0,f(x_0) (x0,f(x0)的切线,此时切线方程为 y = f ( x 0 ) + f ′ ( x 0 ) ( x − x 0 ) y=f(x_0)+f^{'}(x_0)(x-x_0) y=f(x0)+f′(x0)(x−x0),与x轴的交点为 x 1 x_1 x1, x 1 = x 0 − f ( x 0 ) / f ′ ( x 0 ) = x 0 − ( x 0 2 − n ) / 2 x 0 = 1 / 2 ( x 0 + n / x 0 ) x_1=x_0 - f(x_0)/f^{'}(x_0)=x_0-(x^2_0-n)/2x_0=1/2(x_0+n/x_0) x1=x0−f(x0)/f′(x0)=x0−(x02−n)/2x0=1/2(x0+n/x0)
- 同理,取 x = x 1 x=x_1 x=x1,走1的流程,此时,可得迭代公式 x i + 1 = ( x i + n / x i ) / 2 x_{i+1} = (x_i+n/x_i)/2 xi+1=(xi+n/xi)/2
- 根据迭代公式不断迭代,知道找到满足条件的x。
其中,f’(x) 表示 f(x) 的导数。我们可以通过对$ f(x)=x^2-361800 $求导得到
f
′
(
x
)
=
2
x
f'(x)=2x
f′(x)=2x。
因此,我们可以将迭代公式应用于我们的问题,得到:
x
1
=
x
0
−
(
x
0
2
−
361800
)
/
(
2
∗
x
0
)
x_1 = x_0 - (x_0^2 - 361800)/(2*x_0)
x1=x0−(x02−361800)/(2∗x0), 将
x
0
=
600
x_0=600
x0=600 代入该公式,得到:
x
1
=
600
−
(
60
0
2
−
361800
)
/
(
2
∗
600
)
=
601.5
x_1 = 600 - (600^2 - 361800)/(2*600) = 601.5
x1=600−(6002−361800)/(2∗600)=601.5将 x_1=601.5 代入该公式,得到:
x
2
=
601.5
−
(
601.
5
2
−
361800
)
/
(
2
∗
601.5
)
=
600.0382
x_2 = 601.5 - (601.5^2 - 361800)/(2*601.5) = 600.0382
x2=601.5−(601.52−361800)/(2∗601.5)=600.0382重复这个过程,直到收敛到所需精度为止。可以发现,这种方法是非常快速和有效的。
2. 给定一个一维正数数组 A,找出该数组中的极大值位置。请给出快速算法(比较次数最少)。举例:假设数组 A = [7, 5, 6, 5, 4, 3, 5, 7, 1],则极大值点位置为[0, 2, 7]
可以使用一种基于二分查找的算法来快速找到数组 A 中的极大值位置。具体来说,我们可以利用中间位置 mid 将数组 A 分成左右两个子数组,然后比较 A[mid-1]、A[mid] 和 A[mid+1] 三个位置的大小关系,判断出极大值在左半部分、右半部分还是在 mid 位置上,然后递归地在对应的子数组中查找极大值。
下面是具体的实现步骤:
-
初始化左右边界 left 和 right,分别为数组 A 的第一个和最后一个位置。
-
在一个循环中执行以下操作:
a. 计算中间位置 mid,即 mid = (left + right) // 2。
b. 如果 mid 是数组 A 中的第一个位置或最后一个位置,那么 A[mid] 就是极大值,返回 mid。
c. 否则,比较 A[mid-1]、A[mid] 和 A[mid+1] 三个位置的大小关系:
i. 如果 A[mid-1] < A[mid] > A[mid+1],那么 A[mid] 就是极大值,返回 mid。
ii. 如果 A[mid-1] < A[mid] < A[mid+1],那么极大值在右半部分,将 left 更新为 mid+1。
iii. 否则,极大值在左半部分,将 right 更新为 mid-1。
- 如果没有找到极大值,返回一个空列表。
下面是 Python 代码实现:
def find_peak(A):
n = len(A)
if n == 0:
return []
left, right = 0, n - 1
while left < right:
mid = (left + right) // 2
if mid == 0:
return [0] if A[0] > A[1] else []
elif mid == n - 1:
return [n-1] if A[n-1] > A[n-2] else []
elif A[mid-1] < A[mid] > A[mid+1]:
return [mid]
elif A[mid-1] < A[mid] < A[mid+1]:
left = mid + 1
else:
right = mid - 1
return []
该算法的时间复杂度为 O(log N),其中 N 是数组 A 的长度。由于每次比较都将数组的大小减半,因此比较次数最多为 log N。
3. 数组 A 包含 10 亿条数据,数组 B 包含 3000 条数据,每条数据为形如"[1.0, 5.4, 0.0, 2.6, 3.0, 2.5, 7.9 ]"的浮点型数组。现在要对数组 A 和数组 B 进行匹配,如果 A[i]和 B[j]有 3 个及其以上的数字相同则认为他们是匹配的,请给出数组A 和数组 B 匹配的方法。(数组 A 中的任意一条数据可以和数组 B 中的 0 个或多个数据匹配,反之亦然)。
可以使用一种基于二分查找的算法来快速找到数组 A 中的极大值位置。具体来说,我们可以利用中间位置 mid 将数组 A 分成左右两个子数组,然后比较 A[mid-1]、A[mid] 和 A[mid+1] 三个位置的大小关系,判断出极大值在左半部分、右半部分还是在 mid 位置上,然后递归地在对应的子数组中查找极大值。
下面是具体的实现步骤:
- 初始化左右边界 left 和 right,分别为数组 A 的第一个和最后一个位置。
- 在一个循环中执行以下操作:
a. 计算中间位置 mid,即 mid = (left + right) // 2。
b. 如果 mid 是数组 A 中的第一个位置或最后一个位置,那么 A[mid] 就是极大值,返回 mid。
c. 否则,比较 A[mid-1]、A[mid] 和 A[mid+1] 三个位置的大小关系:
i. 如果 A[mid-1] < A[mid] > A[mid+1],那么 A[mid] 就是极大值,返回 mid。
ii. 如果 A[mid-1] < A[mid] < A[mid+1],那么极大值在右半部分,将 left 更新为 mid+1。
iii. 否则,极大值在左半部分,将 right 更新为 mid-1。
- 如果没有找到极大值,返回一个空列表。
下面是 Python 代码实现:
def find_peak(A):
n = len(A)
if n == 0:
return []
left, right = 0, n - 1
while left < right:
mid = (left + right) // 2
if mid == 0:
return [0] if A[0] > A[1] else []
elif mid == n - 1:
return [n-1] if A[n-1] > A[n-2] else []
elif A[mid-1] < A[mid] > A[mid+1]:
return [mid]
elif A[mid-1] < A[mid] < A[mid+1]:
left = mid + 1
else:
right = mid - 1
return []
该算法的时间复杂度为 O(log N),其中 N 是数组 A 的长度。由于每次比较都将数组的大小减半,因此比较次数最多为 log N。
4. 小智有 N 张银行卡(卡内余额均以万为单位),请帮小智从中找到 3张卡使得卡内余额总数恰好是 250w。如果有多种不同的组合请给出所有这些可能的组合。
这个问题可以使用暴力枚举法来解决,即枚举所有可能的三张卡,并计算它们的余额总数,判断是否等于 250。
下面是具体的实现步骤:
- 对银行卡余额数组进行从小到大排序。
- 在三重循环中枚举所有可能的三张卡,并计算它们的余额总数。
- 如果余额总数等于 250,则将这三张卡的编号存入结果列表。
下面是 Python 代码实现:
def find_cards(balance):
n = len(balance)
balance.sort()
res = []
for i in range(n):
for j in range(i+1, n):
for k in range(j+1, n):
total = balance[i] + balance[j] + balance[k]
if total == 250:
res.append([i, j, k])
return res