美团广告算法工程师
一、求平方根(力扣69. x 的平方根 )
- 思路:这里只需要保留整数部分,换句话说就是求输入的非负整数 x,返回最大的非负整数m,满足 x 2 < = x x^2 <= x x2<=x。使用二分查找解决。
- 代码:
class Solution:
def mySqrt(self, x):
left, right = 0, min(x+1, 46341)
while left + 1 < right:
m = (left + right) // 2
if m * m <= x:
left = m
else:
right = m
# 循环结束:left + 1 = right
return left
二、手撕 sqrt(x):牛顿迭代法 & 梯度下降法
2.1. 牛顿迭代法(Newton-Raphson)
- 目标: 求解 f ( x ) = x 2 − a = 0 f(x) = x^2 - a = 0 f(x)=x2−a=0 的正根(即 a \sqrt{a} a)
- 推导:
- 设 f ( x ) = x 2 − a f(x) = x^2 - a f(x)=x2−a, f ′ ( x ) = 2 x f'(x) = 2x f′(x)=2x
- 牛顿迭代公式:
x n + 1 = x n − f ( x n ) f ′ ( x n ) = 1 2 ( x n + a x n ) x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)} = \frac{1}{2}(x_n + \frac{a}{x_n}) xn+1=xn−f′(xn)f(xn)=21(xn+xna)
- 代码实现(Python):
def sqrt_newton(a, tol=1e-6, max_iter=100):
if a < 0:
raise ValueError("不能对负数开平方")
if a == 0:
return 0
x = a / 2
for _ in range(max_iter):
x_next = 0.5 * (x + a / x)
if abs(x - x_next) < tol:
break
x = x_next
return x
2.2. 使用梯度下降法
我们要计算
a
\sqrt{a}
a,可以将其转化为一个优化问题:
min
x
(
x
2
−
a
)
2
\min_x (x^2 - a)^2
xmin(x2−a)2
这个函数在
x
=
a
x = \sqrt{a}
x=a 和
x
=
−
a
x = -\sqrt{a}
x=−a 处取最小值(为0),因此通过最小化这个目标函数,可以求得平方根。
设:
- 目标函数: f ( x ) = ( x 2 − a ) 2 f(x) = (x^2 - a)^2 f(x)=(x2−a)2
- 梯度(导数): ∇ f ( x ) = d d x [ ( x 2 − a ) 2 ] = 4 x ( x 2 − a ) \nabla f(x) = \frac{d}{dx}[(x^2 - a)^2] = 4x(x^2 - a) ∇f(x)=dxd[(x2−a)2]=4x(x2−a)
2.2.1. 梯度下降更新公式
x n + 1 = x n − η ⋅ 4 x n ( x n 2 − a ) x_{n+1} = x_n - \eta \cdot 4x_n(x_n^2 - a) xn+1=xn−η⋅4xn(xn2−a)
其中:
- η \eta η 是学习率(learning rate)
- x n x_n xn 是当前估计值
2.2.2. Python 实现
def sqrt_gd(a, lr=0.01, tol=1e-6, max_iter=10000):
if a < 0:
raise ValueError("不能对负数开平方")
if a == 0:
return 0
x = a / 2 # 初始值
for _ in range(max_iter):
grad = 4 * x * (x ** 2 - a)
x_next = x - lr * grad
if abs(x - x_next) < tol:
break
x = x_next
return x
三、广告算法中,为什么要建模用户的中间行为(如CTR、CVR),而不是直接建模eCPM?
3.1. 中间行为建模能更好地捕捉因果结构
广告行为流程通常是:展示 → 点击 → 转化,存在天然的因果关系:
- CTR(点击率):展示后是否点击
- CVR(转化率):点击后是否转化
- eCPM(有效千次展示收益):bid × pCTR(或更复杂公式,如 bid × pCTR × pCVR × 值)
直接建模 eCPM 会混淆这些阶段,模型无法学习明确的用户行为逻辑。而分阶段建模,更贴合业务流程、可解释性更强。
3.2. 中间任务易于监督、更易训练
- CTR 与 CVR 是清晰的二分类任务,历史数据丰富、监督信号明确;
- eCPM 是组合指标,受出价、用户行为、策略等多因素影响,难以作为有效 label;
- 中间行为建模训练更稳定、收敛更快。
- 支持独立训练 CTR / CVR 模型,调试方便;
- 方便组合策略模型(如出价策略、排序策略);
- 容易扩展为多任务结构,如加上兴趣预测、曝光校准等模块。
3.3. 中间建模支持多目标调控和多业务场景适配
- 不同业务目标:点击、转化、ROI、GMV 等;
- 可根据业务需求灵活组合公式,例如:
pCTR × bid pCTR × pCVR × 商品价值
- 多目标调度、多策略匹配更灵活。
3.4. 直接建模 eCPM 存在缺陷
- bid 变化大,导致 eCPM 不稳定;
- 高 eCPM 样本稀缺,训练难度大;
- 易受竞价机制变化影响,泛化能力差;
- 缺乏清晰可解释性,不利于运维和策略调试。
3.5. 多任务学习
- 多任务学习(MTL)下同时建模 CTR / CVR / eCPM 的方法;
- 预估 + 策略分离的排序架构;
- 基于用户生命周期价值(LTV)的联合建模策略。
四、437. 路径总和 III
- 思路:这道题和之前的和为k的子数组是一个方法,也就是前缀和。
- 代码:
class Solution:
def pathSum(self, root):
ans = 0
cnt = collections.dafaultdict(int)
cnt[0] = 1
def dfs(node, s):
if node is None:
return
nonlocal ans
s += node.val
ans += cnt[s-targetSum]
cnt[s] += 1
dfs(node.left, s)
dfs(node.right, s)
cnt[s] -= 1
dfs(root, 0)
return ans