题目
思路
这道题虽然能明确想到是贪心思想,但是具体的算法不容易想到。首先为了能直观快速找到经过处理后数组的最大值和最小值,需要对数组进行排序。之后再考虑的时候应该尽量上较小的值变大,较大的值变小(使它们更加接近)。这里的变大变小应该从区间的角度思考,即某一个区间的值全部变大,后面区间的值全部缩小(这里很难给出严谨的证明,但是如果不考虑区间,只考虑原有的最大最小值或类似算法很难考虑到所有情况)。所以需要枚举增大区间和减小区间的临界点(即遍历数组),因为当前数组已经排序,所以处理过后的数组最大值在两端数组的极大值中产生,最小值在两端数组中的极小值中产生。算法时间复杂度为O()
代码
class Solution:
def smallestRangeII(self, A: List[int], K: int) -> int:
A.sort()
n=len(A)
k=K
if n==1:
return 0
ans=float('inf')
for i in range(n-1):
maxx=max(A[i]+k,A[n-1]-k)
minn=min(A[0]+k,A[i+1]-k)
ans=min(ans,maxx-minn)
ans=min(ans,A[n-1]-A[0]) #这里是特殊情况,相当于整个数组都上移或下移,相当于没有变化,此时的最大最小值不变
return ans