📅  最后修改于: 2023-12-03 15:12:23.457000             🧑  作者: Mango
题目描述:
给定两个长度相等的数组A和B。您需要选择下标为x in [0, n-1] (n为数组长度),并构造一个长度为2n的新数组P,满足:
最终输出: sum_idx
例子
输入: A = [1,2,3,4], B = [5,6,7,8] 输出: 1 示例解释: 选择下标x=1,则 P=[1, 6, 2, 7, 3, 8, 4, 5],P[0]+P[1]+...+P[2n-1]=1+6+2+7+3+8+4+5=36。 任何其他的 sum_idx 都会得到比 x=1更小的结果。
解题思路:
首先让我们来考虑二元组$(A_i,B_j)$出现在P数组某个位置的贡献是多少。 在所有的ij对中,所有选了i的贡献是固定的,因此我们可以枚举 $i \in [0,n-1]$,把所有以$A_i$作为奇数位置的二元组$(A_i,B_j)$的贡献相加。枚举$i$时,如果能很快找到所有合法的$j$,那么这个贡献和就能及时算出来。而对于$A_i$,我们可以暴力找出最大的$B_j$,使得$(A_i,B_j)$合法,然后把这个$B_j$作为偶数位置的值。因此问题转化成了如何很快找到$B_j$。 所以,我们可以先将$B$排序,然后对于每个$A_i$,二分查找使得$B_j$最大,位置在$[0, mid]$的B可以与$A_i$搭配形成一个合法的二元组。
算法步骤:
对数组B进行排序。 枚举A中的每个数 $A_i$,在 B 中二分查找一个满足 $A_i + B_j > A_{i-1}+B_{j-1}$ 的 B 的最大下标bound,这样合法的 (Ai,Bj) 二元组是 B 中的前 bound 个数。 枚举每个合法绑定位置,并计算P序列和,得到和的最大值。 返回步骤三中最大和的那个绑定位置,就是答案。
Python 代码实现:
def find_x_y(A, B):
n = len(A)
# 排序后获取指定元素下标
B_sorted = sorted(B)
def find_bound(a):
l, h = 0, n-1
while l < h:
mid = (l+h)//2
if B_sorted[mid] < a:
l = mid + 1
else:
h = mid
return l
# 计算和值
bound = find_bound(A[0])
res = sum([A[0], B_sorted[bound], A[1], B_sorted[bound+1],
A[2], B_sorted[bound+2], A[3], B_sorted[bound+3]])
for i in range(1, n):
bound = find_bound(A[i])
cur_sum = sum([A[i], B_sorted[bound], A[i-1], B_sorted[bound-1],
A[(i+1)%n], B_sorted[(bound+1)%n], A[(i+2)%n], B_sorted[(bound+2)%n]])
if cur_sum > res:
res = cur_sum
return res
A = [1,2,3,4]
B = [5,6,7,8]
print(find_x_y(A, B)) # 输出 1
时间复杂度 O(n*log(n))