LeetCode 0910.最小差值 II:贪心(排序)-小数大数分界线枚举(思考过程详解)

【LetMeFly】910.最小差值 II:贪心(排序)-小数大数分界线枚举(思考过程详解)

力扣题目链接:https://leetcode.cn/problems/smallest-range-ii/

给你一个整数数组 nums,和一个整数 k

对于每个下标 i0 <= i < nums.length),将 nums[i] 变成 nums[i] + knums[i] - k

nums分数nums 中最大元素和最小元素的差值。

在更改每个下标对应的值之后,返回 nums 的最小 分数

示例 1:

复制代码
输入:nums = [1], k = 0
输出:0
解释:分数 = max(nums) - min(nums) = 1 - 1 = 0 。

示例 2:

复制代码
输入:nums = [0,10], k = 2
输出:6
解释:将数组变为 [2, 8] 。分数 = max(nums) - min(nums) = 8 - 2 = 6 。

示例 3:

复制代码
输入:nums = [1,3,6], k = 3
输出:3
解释:将数组变为 [4, 6, 3] 。分数 = max(nums) - min(nums) = 6 - 3 = 3 。

提示:

  • 1 <= nums.length <= 104
  • 0 <= nums[i] <= 104
  • 0 <= k <= 104

解题方法:贪心(排序)

这次每个数必须得变,考虑数组中最小的数 m m m和最大 M M M的数:

  • 如果 m m m和 M M M同时变大/同时变小,则差值 d i f f = M − m diff=M-m diff=M−m;
  • 如果 m m m变小 M M M变大,则差值变大 d i f f = M − m + 2 k ≥ M − m diff=M-m+2k\geq M-m diff=M−m+2k≥M−m;
  • 如果 m m m变大 M M M变小,则差值为 d i f f = a b s ( ( M − k ) − ( m + k ) ) = a b s ( M − m − 2 k ) diff=abs((M-k)-(m+k))=abs(M-m-2k) diff=abs((M−k)−(m+k))=abs(M−m−2k)。

如果 m m m很小 M M M很大,那么那么 m m m变 M M M变小的话差值会变小;如果 m m m和 M M M相差本来不大,那么 m m m变大而 M M M变小的话 d i f f diff diff反而可能会变大。怎么办呢?

其实不难发现,除了最小的数和最大的数,其他较小的数和较大的数也是这样的关系。

我们可以先对数组排个序,然后枚举"小数大数的分界线"。分界线左边的数视为"小数"并且全部 + k +k +k,分界线右边的数视为"大数"并且全部 − k -k −k。

在所有的方案中,差值最小的那个即为所求。

对于一个方案,如何快速计算 d i f f diff diff呢?

假设 n u m s [ 0 ] nums[0] nums[0]到 n u m s [ i ] nums[i] nums[i]每个数 + k +k +k, n u m s [ i + 1 ] nums[i + 1] nums[i+1]到 n u m s [ n − 1 ] nums[n - 1] nums[n−1]每个数 − k -k −k,那么:

数组中最大的数为 n u m s [ i ] + k nums[i] + k nums[i]+k或者 n u m s [ n − 1 ] − k nums[n - 1] - k nums[n−1]−k,最小的数为 n u m s [ i + 1 ] − k nums[i + 1] - k nums[i+1]−k或 n u m s [ 0 ] + k nums[0] + k nums[0]+k。

因此 d i f f = max ⁡ ( n u m s [ i ] + k , n u m s [ l e n ( n u m s ) − 1 ] − k ) − min ⁡ ( n u m s [ i + 1 ] − k , n u m s [ 0 ] + k ) diff=\max(nums[i] + k, nums[len(nums) - 1] - k) - \min(nums[i + 1] - k, nums[0] + k) diff=max(nums[i]+k,nums[len(nums)−1]−k)−min(nums[i+1]−k,nums[0]+k)。

  • 时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),其中 n = l e n ( n u m s ) n=len(nums) n=len(nums)
  • 空间复杂度 O ( log ⁡ n ) O(\log n) O(logn),时空复杂度的开销主要来自排序

AC代码

C++
cpp 复制代码
class Solution {
public:
    int smallestRangeII(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        int ans = nums.back() - nums[0];
        for (int i = 0; i < nums.size() - 1; i++) {  // nums[0..i]变大 nums[i+1..n-1]变小
            ans = min(ans, max(nums[i] + k, nums.back() - k) - min(nums[i + 1] - k, nums[0] + k));
        }
        return ans;
    }
};
Go
go 复制代码
package main

import "slices"

func smallestRangeII(nums []int, k int) int {
    slices.Sort(nums)
    ans := nums[len(nums) - 1] - nums[0]
    for i := 0; i < len(nums) - 1; i++ {
        ans = min(ans, max(nums[i] + k, nums[len(nums) - 1] - k) - min(nums[i + 1] - k, nums[0] + k))
    }
    return ans
}
Java
java 复制代码
import java.util.Arrays;

class Solution {
    public int smallestRangeII(int[] nums, int k) {
        Arrays.sort(nums);
        int ans = nums[nums.length - 1] - nums[0];
        for (int i = 0; i < nums.length - 1; i++) {
            ans = Math.min(ans, Math.max(nums[i] + k, nums[nums.length - 1] - k) - Math.min(nums[i + 1] - k, nums[0] + k));
        }
        return ans;
    }
}
Python
python 复制代码
from typing import List

class Solution:
    def smallestRangeII(self, nums: List[int], k: int) -> int:
        nums.sort()
        ans = nums[-1] - nums[0]
        for i in range(len(nums) - 1):
            ans = min(ans, max(nums[i] + k, nums[-1] - k) - min(nums[i + 1] - k, nums[0] + k))
        return ans

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

Tisfy:https://letmefly.blog.csdn.net/article/details/143136177

相关推荐
ElseWhereR1 分钟前
二进制求和 - 简单
c++·算法·leetcode
天天扭码19 分钟前
LeetCode 题解 | 1.两数之和(最优解)
前端·javascript·算法
亿佛23 分钟前
(Matlab)自动驾驶仿真 设计驾驶场景、配置传感器并生成合成 数据
人工智能·算法·机器学习·自动驾驶·测试用例
胡乱儿起个名38 分钟前
《高阶函数:把函数当玩具传来传去》
开发语言·c++·算法
050208101 小时前
各种排序算法
数据结构·算法·排序算法
不会弹吉他的布鲁克1 小时前
25 年最新大佬 Paper,Transformers再也不需要归一化,这届AI学会“自我管理”了!
算法
小美爱刷题2 小时前
力扣DAY52-54 | 热100 | 图论:腐烂的橘子、课程表、前缀树
算法·leetcode·图论
南梦也要学习2 小时前
STM32江科大----------PID算法
stm32·嵌入式硬件·算法
.普通人2 小时前
算法基础(以acwing讲述顺序为主,结合自己理解,持续更新中...)
c++·算法
brzhang2 小时前
为什么 A2A 和 MCP 缺一不可?
前端·后端·算法