问题描述
小R拿到了一个数组,她可以进行如下操作:使得一个元素加1,另一个元素减1。她希望最终数组的每个元素大小都在[1,r]的范围内。小R想知道,最少需要多少次操作可以达到目标。 如果无法通过有限次操作使所有元素都落在指定范围内,则返回-1。
测试样例
样例1: 输入:n=21=3,r=[1,21] 输出:-1
样例2: 输入:n=3,1=4,r=6,a=[3,6,5]输出:1
样例3: 输入:n=4,1=2r=8,a=[1,10,2,6]输出:2
题目分析
这道题目难点在于考虑清楚什么情况下是满足题目要求的条件的:即可以使所有元素都落在指定范围内。 最开始考虑小于L大于R的元素,但不要忘记了在[1,r]范围内的元素也可以向左向右移动。 所以要统计4个求和:
这个问题的核心是 调整数组元素,使得它们都满足给定的范围 [1, r]
,通过两种操作来调整:一个元素加1,另一个元素减1。目标是最少的操作次数,或者判断是否无法通过有限次操作使所有元素满足条件。
首先,统计出所有小于L的元素与L的差值和suml1。同理求出所有大于r的元素与r的差值和sumr1。
当给出的数据能够达到所有元素移动到范围中时,最终的结果就是max(suml1,sumr1)
同时要统计大于L的元素到L的差值和suml2、小于r的元素到r的差值和sumr2。
由于小于r的元素均可以+1;大于L的元素均可以-1。
所以最终满足条件的数据是sumr1 <= suml2 and suml1 <= sumr2: 解释为suml2代表了所有可减一的元素均减一到l的最大范围;sumr2代表了所有可加一元素均加一到r的最大范围。 这样就得到了最终的满足要求的取值范围。
要注意题目并没有说提供的数据是满足r>=l的,所以要添加判断条件
最终的code如下。
代码解释:
- 初始化:
low_need
和high_need
分别表示需要增加和减少的操作次数。 - 遍历数组:对于每个元素,如果它小于下界
l
,就需要增加到l
,并累加需要增加的次数;如果它大于上界r
,就需要减少到r
,并累加需要减少的次数。 - 判断可行性:如果
low_need
和high_need
不相等,说明无法通过操作调整数组符合条件,返回-1
。如果相等,返回low_need
(或high_need
),即最小操作次数。