第三次算法面 蚂蚁

蚂蚁春招

一共三道算法,很菜,只做出第一道最简单的

第一题忘记了

第二题是一个二叉树的题目,感觉是很简单的,但人太菜,没办法,复习一下二叉树

题目大概如下:

输入如下:

5 2  # 5个节点,问询 2次
1 2  # 节点1增加子节点 2
1 3  # 节点1增加子节点 3
2 4
2 5
3 6  # 第一次问询,节点3与节点6的距离是多少
1 5  # 第二次问询,节点1与节点5的距离是多少

第三题:给出一个数组an = [a1, a2, ..., an]

题目要求直接写的话是这样:但肯定需要优化一下算法才行

an = [1,2,5,6,2,1,5,2222,11111,2222, ...]
sum = 0
for i in an:
	for j in an:
		sum += i //j
print(sum)

优化后的代码(来自deepseek)使用_small_m_or_low_max就足够了,还是见得少了,这个没想到

from collections import defaultdict
import bisect
import math

def dynamic_optimized_sum(an):
    freq = defaultdict(int)
    for num in an:
        freq[num] += 1
    sorted_j = sorted(freq.keys())
    m = len(sorted_j)
    max_i = max(sorted_j) if m > 0 else 0
    
    # 选择策略:根据m和max_i决定算法
    if m <= 1000 or max_i <= 1e5:
        return _small_m_or_low_max(freq, sorted_j)
    else:
        return _large_m_or_high_max(freq, sorted_j, max_i)

def _small_m_or_low_max(freq, sorted_j):
    total = 0
    for j_val in sorted_j:
        if j_val == 0:
            continue
        cnt_j = freq[j_val]
        sum_i = 0
        for i_val in freq:
            sum_i += (i_val // j_val) * freq[i_val]
        total += sum_i * cnt_j
    return total

def _large_m_or_high_max(freq, sorted_j, max_i):
    prefix = [0] * (len(sorted_j) + 1)
    for i in range(len(sorted_j)):
        prefix[i + 1] = prefix[i] + freq[sorted_j[i]]
    total = 0
    for i_val in freq:
        cnt_i = freq[i_val]
        if i_val == 0:
            continue
        sum_j_part = 0
        sqrt_i = int(math.isqrt(i_val))
        # 处理小j_val (j <= sqrt(i_val))
        pos = bisect.bisect_right(sorted_j, sqrt_i)
        for j in sorted_j[:pos]:
            if j == 0:
                continue
            q = i_val // j
            sum_j_part += q * freq[j]
        # 处理大j_val (j > sqrt(i_val)),数论分块
        for q in range(1, sqrt_i + 1):
            lower = (i_val // (q + 1)) + 1
            upper = i_val // q
            if lower > upper:
                continue
            left = bisect.bisect_left(sorted_j, lower)
            right = bisect.bisect_right(sorted_j, upper)
            count = prefix[right] - prefix[left]
            sum_j_part += q * count
        total += sum_j_part * cnt_i
    return total

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务