LeetCode 题解工作台

选出和最大的 K 个元素

给你两个整数数组, nums1 和 nums2 ,长度均为 n ,以及一个正整数 k 。 对从 0 到 n - 1 每个下标 i ,执行下述操作: 找出所有满足 nums1[j] 小于 nums1[i] 的下标 j 。 从这些下标对应的 nums2[j] 中选出 至多 k 个,并 最大化 这些值的总…

category

3

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

中等 · 数组·排序

bolt

答案摘要

我们可以将数组 转换成一个数组 ,其中每个元素是一个二元组 $(x, i)$,表示 的值为 。然后对数组 按照 进行升序排序。 我们使用一个小根堆 来维护数组 中的元素,初始时 为空。用一个变量 来记录 中的元素之和。另外,我们用一个指针 来维护当前需要添加到 中的元素在数组 中的位置。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 数组·排序 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你两个整数数组,nums1nums2,长度均为 n,以及一个正整数 k

对从 0n - 1 每个下标 i ,执行下述操作:

  • 找出所有满足 nums1[j] 小于 nums1[i] 的下标 j
  • 从这些下标对应的 nums2[j] 中选出 至多 k 个,并 最大化 这些值的总和作为结果。

返回一个长度为 n 的数组 answer ,其中 answer[i] 表示对应下标 i 的结果。

 

示例 1:

输入:nums1 = [4,2,1,5,3], nums2 = [10,20,30,40,50], k = 2

输出:[80,30,0,80,50]

解释:

  • 对于 i = 0 :满足 nums1[j] < nums1[0] 的下标为 [1, 2, 4] ,选出其中值最大的两个,结果为 50 + 30 = 80
  • 对于 i = 1 :满足 nums1[j] < nums1[1] 的下标为 [2] ,只能选择这个值,结果为 30
  • 对于 i = 2 :不存在满足 nums1[j] < nums1[2] 的下标,结果为 0
  • 对于 i = 3 :满足 nums1[j] < nums1[3] 的下标为 [0, 1, 2, 4] ,选出其中值最大的两个,结果为 50 + 30 = 80
  • 对于 i = 4 :满足 nums1[j] < nums1[4] 的下标为 [1, 2] ,选出其中值最大的两个,结果为 30 + 20 = 50

示例 2:

输入:nums1 = [2,2,2,2], nums2 = [3,1,2,3], k = 1

输出:[0,0,0,0]

解释:由于 nums1 中的所有元素相等,不存在满足条件 nums1[j] < nums1[i],所有位置的结果都是 0 。

 

提示:

  • n == nums1.length == nums2.length
  • 1 <= n <= 105
  • 1 <= nums1[i], nums2[i] <= 106
  • 1 <= k <= n
lightbulb

解题思路

方法一:排序 + 优先队列(小根堆)

我们可以将数组 nums1\textit{nums1} 转换成一个数组 arr\textit{arr},其中每个元素是一个二元组 (x,i)(x, i),表示 nums1[i]\textit{nums1}[i] 的值为 xx。然后对数组 arr\textit{arr} 按照 xx 进行升序排序。

我们使用一个小根堆 pq\textit{pq} 来维护数组 nums2\textit{nums2} 中的元素,初始时 pq\textit{pq} 为空。用一个变量 s\textit{s} 来记录 pq\textit{pq} 中的元素之和。另外,我们用一个指针 jj 来维护当前需要添加到 pq\textit{pq} 中的元素在数组 arr\textit{arr} 中的位置。

我们遍历数组 arr\textit{arr},对于第 hh 个元素 (x,i)(x, i),我们将所有满足 j<hj < h 并且 arr[j][0]<x\textit{arr}[j][0] < x 的元素 nums2[arr[j][1]]\textit{nums2}[\textit{arr}[j][1]] 添加到 pq\textit{pq} 中,并将这些元素的和加到 s\textit{s} 中。如果 pq\textit{pq} 的大小超过了 kk,我们将 pq\textit{pq} 中的最小元素弹出,并将其从 s\textit{s} 中减去。然后,我们更新 ans[i]\textit{ans}[i] 的值为 s\textit{s}

遍历结束后,返回答案数组 ans\textit{ans}

时间复杂度 O(n×logn)O(n \times \log n),空间复杂度 O(n)O(n)。其中 nn 为数组长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
    def findMaxSum(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:
        arr = [(x, i) for i, x in enumerate(nums1)]
        arr.sort()
        pq = []
        s = j = 0
        n = len(arr)
        ans = [0] * n
        for h, (x, i) in enumerate(arr):
            while j < h and arr[j][0] < x:
                y = nums2[arr[j][1]]
                heappush(pq, y)
                s += y
                if len(pq) > k:
                    s -= heappop(pq)
                j += 1
            ans[i] = s
        return ans
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Checks the candidate's ability to leverage sorting and heap-based techniques.

  • question_mark

    Assesses understanding of efficient summation strategies and matching.

  • question_mark

    Evaluates problem-solving under the constraints of time complexity.

warning

常见陷阱

外企场景
  • error

    Overcomplicating the summation process without using heap-based optimization.

  • error

    Failing to match nums1 and nums2 correctly after sorting.

  • error

    Incorrectly handling cases where the k elements are not properly selected from nums2.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Varying the value of k to test the performance and efficiency of the solution.

  • arrow_right_alt

    Testing with larger arrays and ensuring the algorithm handles large inputs efficiently.

  • arrow_right_alt

    Changing the relationship between nums1 and nums2 to introduce edge cases in the pairing logic.

help

常见问题

外企场景

选出和最大的 K 个元素题解:数组·排序 | LeetCode #3478 中等