561. Array PartitionI

本文介绍了一种通过排序和选择偶数位置元素的方法来解决数组配对求和问题,使得所选元素之和尽可能大。

Given an array of 2n integers, your task is to group these integers
into n pairs of integer, say (a1, b1), (a2, b2), …, (an, bn) which
makes sum of min(ai, bi) for all i from 1 to n as large as possible.

题目描述:给你一个长度为2n的数组,分组为n个组,取出每个组中的最小值,求这些最小值之和的最大值

思路:这个题只要你将这个数组在纸上写出来就能很容易的找到方法,
如何让sum 最大化呢,我们想一下,如果是两个数字,一个很小,一个很大,这样的话,
取一个小的数字,就浪费了那个大的数字。所以我们要使每一对的两个数字尽可能接近,这样得到的值就尽可能的最大化

例如 n1 n2 n3 n4 n5 n6 n7 n8 …..

其中和为最大值的取值为:n1+n3+n5+n7….+2n(n-1)
和为最小值的取值为:n1+n2+n3+n4…+n(n-1)

 public int arrayPairSum(int[] nums) {

        Arrays.sort(nums);
        int sum=0;
        for (int i =0;i<nums.length;i=i+2){
            sum+=nums[i];
        }
        return sum;
    }
<think> 我们正在讨论`np.partition(x, n)`函数。这个函数是NumPy中用于部分排序的函数,它能够高效地重新排列数组,使得第n个位置的元素是排序后应处的正确位置,同时该元素左侧的所有元素都小于等于它,右侧的所有元素都大于等于它。但注意,左右两侧的元素并不保证有序。 ### 功能原理 `np.partition(x, n)`的原理基于快速选择算法,这是一种从无序列表中选择第k小(或大)元素的高效算法,平均时间复杂度为$O(n)$。该函数执行步骤如下: 1. 选取数组`x`中任意一个元素作为基准(pivot)。 2. 将数组划分为两部分:小于等于基准的元素放在左边,大于等于基准的元素放在右边。 3. 如果基准的最终位置恰好是索引`n`,则停止;否则,在包含目标索引的那一部分中递归执行上述步骤。 最终,索引`n`处的元素是排序后应处的元素,且左边的元素都小于等于它,右边的元素都大于等于它。注意,左右两部分内部并不有序。 ### 使用方法 函数签名: ```python numpy.partition(a, kth, axis=-1, kind='introselect', order=None) ``` - `a`: 输入数组。 - `kth`: 一个整数或整数序列,指定将哪个(些)位置的元素放到排序后应处的正确位置。注意,如果提供多个索引,则每个索引对应的位置都会是排序后应处的值,并且整个数组在这些位置之间划分。 - `axis`(可选): 沿着哪个轴进行划分,默认为最后一个轴。 - `kind`(可选): 选择算法,一般为'introselect'(内省选择),它在大多数情况下表现良好。 - `order`(可选): 当数组是结构化数组时,用于指定比较的字段。 返回:划分后的数组(与输入数组同形状)。 ### 示例 #### 示例1: 基本使用 ```python import numpy as np arr = np.array([3, 2, 6, 1, 5, 4]) # 我们希望第3小的元素(索引为2,因为从0开始)在正确位置 result = np.partition(arr, 2) print(result) ``` 输出可能是: ``` [1 2 3 6 5 4] ``` 解释:索引2的位置(第三个元素)是3,它确实是第三小的数。3左边的元素(1,2)都小于等于3,右边的元素(6,5,4)都大于等于3。 #### 示例2: 多个kth ```python arr = np.array([10, 1, 9, 8, 3, 4, 2, 7, 6, 5]) # 我们希望第3小(索引2)和第6小(索引5)的元素在正确位置 result = np.partition(arr, [2, 5]) print(result) ``` 输出可能是: ``` [ 1 2 3 5 4 6 8 7 9 10] ``` 解释: - 索引2处的元素是3(第三小),索引5处的元素是6(第六小)。 - 索引0到2(前三个)的元素都小于等于3(即1,2,3)。 - 索引3到5的元素在3和6之间(这里我们看到5,4,6,注意4和5都小于6,但大于3)。 - 索引6到9的元素都大于等于6。 注意:多个kth时,划分会保证每个kth指定的位置都是正确的,并且划分区间是连续的。 #### 示例3: 多维数组 ```python arr = np.array([[3, 2, 1], [6, 5, 4]]) # 沿着最后一个轴(即每行内部)进行划分,以第1个位置(索引1)为划分点 result = np.partition(arr, 1, axis=-1) print(result) ``` 输出: ``` [[1 2 3] # 第一行:索引1的位置是2,左边1<=2,右边3>=2 [4 5 6]] # 第二行:索引1的位置是5,左边4<=5,右边6>=5 ``` ### 注意事项 1. **时间复杂度**:平均$O(n)$,最坏情况$O(n^2)$,但由于使用了内省选择(introselect),最坏情况在实际中很少见。 2. **稳定性**:划分操作是不稳定的,即相等元素的相对位置可能改变。 3. **应用场景**:当需要获取数组的前k小(或前k大)元素而不需要完全排序时,使用`np.partition`比完全排序($O(n\log n)$)更高效。 ### 相关函数 - `np.argpartition`: 返回划分后元素的原始索引,便于从原始数组中获取划分后的值。 - `np.sort`: 完全排序。 ### 相关问题 1. 如何使用`np.argpartition`函数获取数组中最小的k个元素的索引? 2. 在什么情况下应该使用部分排序而不是完全排序? 3. `np.partition`函数的时间复杂度如何分析? </think> ### `np.partition(x, n)` 详解 `np.partition(x, n)` 是 NumPy 中用于**部分排序**的高效函数,其核心原理基于快速选择算法(Quickselect)。它能在 $O(n)$ 平均时间复杂度内完成操作,比完全排序($O(n\log n)$)更高效。 --- #### **功能原理** 1. **划分机制** 将数组 `x` 重新排列,使得: - 索引 `n` 位置的元素是其排序后应处的正确位置 - 所有 `n` 左侧元素 $\leq$ `x[n]` - 所有 `n` 右侧元素 $\geq$ `x[n]` 数学表达: $$ \forall i < n,\ x_{\text{part}}[i] \leq x_{\text{part}}[n] \quad \text{且} \quad \forall j > n,\ x_{\text{part}}[j] \geq x_{\text{part}}[n] $$ 2. **算法基础** 基于快速排序的分区思想,但不保证左右两侧完全有序(仅保证相对基准值的大小关系)。 --- #### **参数说明** ```python numpy.partition(a, kth, axis=-1, kind='introselect', order=None) ``` - **`a`**:输入数组 - **`kth`**:关键参数 - 整数:划分点的索引位置(如 `n=3` 表示第4小元素) - 列表:支持多划分点(如 `kth=[2,5]`) - **`axis`**:操作轴(默认最后一个轴) - **`kind`**:选择算法(通常为 `'introselect'`) - **`order`**:结构化数组的排序字段 --- #### **使用示例** ##### 1. 基本划分(单索引) ```python import numpy as np x = np.array([30, 10, 40, 20, 50]) # 将第2小元素(索引1)放到正确位置 result = np.partition(x, 1) print(result) # 输出: [10 20 40 30 50] # 解释: # - 索引1的值20是第2小元素 # - 左侧 [10] ≤ 20 # - 右侧 [40,30,50] ≥ 20(但不保证右侧有序) ``` ##### 2. 多划分点 ```python x = np.array([5, 8, 1, 3, 6, 2, 7, 4]) # 同时划分第2小(索引1)和第5小(索引4)元素 result = np.partition(x, [1, 4]) print(result) # 可能输出: [1 2 3 4 5 6 7 8] # 解释: # - 索引1的值2是第2小 # - 索引4的值5是第5小 # - [1] ≤ 2 ≤ [3,4] ≤ 5 ≤ [6,7,8] ``` ##### 3. 多维数组应用 ```python arr = np.array([[9, 2, 5], [7, 1, 8]]) # 沿每行划分,取第1小元素(索引0) result = np.partition(arr, 0, axis=1) print(result) # 输出: # [[2 5 9] # 索引0的值2是该行最小 # [1 7 8]] # 索引0的值1是该行最小 ``` --- #### **注意事项** 1. **非稳定性** 不保留相等元素的原始顺序(非稳定排序)。 2. **性能优势** 当只需部分元素(如前k小值)时,比 `np.sort()` 更高效: - `np.partition(x, k)[:k]` → 前k小值 - `np.partition(x, -k)[-k:]` → 前k大值 3. **内存效率** 直接修改数组视图,默认返回新数组(需用 `a.partition(...)` 进行原地操作)。 --- #### **与相关函数对比** | 函数 | 特点 | 时间复杂度 | |-----------------------|--------------------------|--------------| | `np.partition(x, n)` | 部分排序 | $O(n)$ | | `np.sort(x)` | 完全排序 | $O(n\log n)$ | | `np.argpartition()` | 返回划分后的索引 | $O(n)$ | --- ### 相关问题 1. 如何用 `np.partition()` 高效获取数组中第k小的元素? 2. `np.partition()` 和 `np.argpartition()` 的主要区别是什么? 3. 在多维数组中如何沿指定轴进行部分排序?[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值