[LeetCode] 910. Smallest Range II

CNoodle發表於2024-10-21

You are given an integer array nums and an integer k.

For each index i where 0 <= i < nums.length, change nums[i] to be either nums[i] + k or nums[i] - k.

The score of nums is the difference between the maximum and minimum elements in nums.

Return the minimum score of nums after changing the values at each index.

Example 1:
Input: nums = [1], k = 0
Output: 0
Explanation: The score is max(nums) - min(nums) = 1 - 1 = 0.

Example 2:
Input: nums = [0,10], k = 2
Output: 6
Explanation: Change nums to be [2, 8]. The score is max(nums) - min(nums) = 8 - 2 = 6.

Example 3:
Input: nums = [1,3,6], k = 3
Output: 3
Explanation: Change nums to be [4, 6, 3]. The score is max(nums) - min(nums) = 6 - 3 = 3.

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

最小差值 II。

給你一個整數陣列 nums,和一個整數 k 。

對於每個下標 i(0 <= i < nums.length),將 nums[i] 變成 nums[i] + k 或 nums[i] - k 。

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

在更改每個下標對應的值之後,返回 nums 的最小 分數 。

思路

這道題是 908 題的版本二,題意跟 908 題稍有不同。在這道題裡,對於每個元素 nums[i] 而言,你必須做 +k 或 -k 的操作。這道題我參考了這個帖子,寫的很好,圖示也很清楚。

如果沒有 k,那麼這道題和 908 題一樣,直接求最大值和最小值差值即可。但是因為牽涉到 k 的操作了,而且我們要找的這個差值 (max - min) 需要儘可能小,所以基本的思路是要讓小的數字儘可能大(那就 + k),讓大的數字儘可能小(那就 - k)。但是在操作的過程中極有可能導致 min + kmax - k要大。所以我們不能只考慮這兩個值,還要考慮中間的那些值。

所以對於任何一箇中間的 index i 而言,他左側的元素是 nums[0] 到 nums[i - 1];他右側的元素是 nums[i] 到 nums[n - 1]nums[0] 到 nums[i - 1] 都要 + k,nums[i] 到 nums[n - 1] 都要 - k。

這樣一來,

  • 最大值就是 nums[n - 1] - knums[i - 1] + k 的最大值
  • 最小值就是 nums[i] - knums[0] + k 的最小值

複雜度

時間O(nlogn) - sort
空間O(1)

程式碼

Java實現

class Solution {
    public int smallestRangeII(int[] nums, int k) {
        int n = nums.length;
		Arrays.sort(nums);
		int min = nums[0];
        int max = nums[n - 1];
        int res = max - min;
        for (int i = 1; i < n; i++) {
            max = Math.max(nums[i - 1] + k, nums[n - 1] - k);
            min = Math.min(nums[0] + k, nums[i] - k);
            res = Math.min(res, max - min);
        }
		return res;
    }
}

相關文章