加载中...
1906-查询差绝对值的最小值(Minimum Absolute Difference Queries)
发表于:2021-12-03 | 分类: 中等
字数统计: 454 | 阅读时长: 2分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/minimum-absolute-difference-queries

英文原文

The minimum absolute difference of an array a is defined as the minimum value of |a[i] - a[j]|, where 0 <= i < j < a.length and a[i] != a[j]. If all elements of a are the same, the minimum absolute difference is -1.

  • For example, the minimum absolute difference of the array [5,2,3,7,2] is |2 - 3| = 1. Note that it is not 0 because a[i] and a[j] must be different.

You are given an integer array nums and the array queries where queries[i] = [li, ri]. For each query i, compute the minimum absolute difference of the subarray nums[li...ri] containing the elements of nums between the 0-based indices li and ri (inclusive).

Return an array ans where ans[i] is the answer to the ith query.

A subarray is a contiguous sequence of elements in an array.

The value of |x| is defined as:

  • x if x >= 0.
  • -x if x < 0.

 

Example 1:

Input: nums = [1,3,4,8], queries = [[0,1],[1,2],[2,3],[0,3]]
Output: [2,1,4,1]
Explanation: The queries are processed as follows:
- queries[0] = [0,1]: The subarray is [1,3] and the minimum absolute difference is |1-3| = 2.
- queries[1] = [1,2]: The subarray is [3,4] and the minimum absolute difference is |3-4| = 1.
- queries[2] = [2,3]: The subarray is [4,8] and the minimum absolute difference is |4-8| = 4.
- queries[3] = [0,3]: The subarray is [1,3,4,8] and the minimum absolute difference is |3-4| = 1.

Example 2:

Input: nums = [4,5,2,2,7,10], queries = [[2,3],[0,2],[0,5],[3,5]]
Output: [-1,1,1,3]
Explanation: The queries are processed as follows:
- queries[0] = [2,3]: The subarray is [2,2] and the minimum absolute difference is -1 because all the
  elements are the same.
- queries[1] = [0,2]: The subarray is [4,5,2] and the minimum absolute difference is |4-5| = 1.
- queries[2] = [0,5]: The subarray is [4,5,2,2,7,10] and the minimum absolute difference is |4-5| = 1.
- queries[3] = [3,5]: The subarray is [2,7,10] and the minimum absolute difference is |7-10| = 3.

 

Constraints:

  • 2 <= nums.length <= 105
  • 1 <= nums[i] <= 100
  • 1 <= queries.length <= 2 * 104
  • 0 <= li < ri < nums.length

中文题目

一个数组 a 的 差绝对值的最小值 定义为:0 <= i < j < a.length 且 a[i] != a[j] 的 |a[i] - a[j]|最小值。如果 a 中所有元素都 相同 ,那么差绝对值的最小值为 -1 。

  • 比方说,数组 [5,2,3,7,2] 差绝对值的最小值是 |2 - 3| = 1 。注意答案不为 0 ,因为 a[i] 和 a[j] 必须不相等。

给你一个整数数组 nums 和查询数组 queries ,其中 queries[i] = [li, ri] 。对于每个查询 i ,计算 子数组 nums[li...ri] 中 差绝对值的最小值 ,子数组 nums[li...ri] 包含 nums 数组(下标从 0 开始)中下标在 li 和 ri 之间的所有元素(包含 li 和 ri 在内)。

请你返回 ans 数组,其中 ans[i] 是第 i 个查询的答案。

子数组 是一个数组中连续的一段元素。

|x| 的值定义为:

  • 如果 x >= 0 ,那么值为 x 。
  • 如果 x < 0 ,那么值为 -x 。

 

示例 1:

输入:nums = [1,3,4,8], queries = [[0,1],[1,2],[2,3],[0,3]]
输出:[2,1,4,1]
解释:查询结果如下:
- queries[0] = [0,1]:子数组是 [1,3] ,差绝对值的最小值为 |1-3| = 2 。
- queries[1] = [1,2]:子数组是 [3,4] ,差绝对值的最小值为 |3-4| = 1 。
- queries[2] = [2,3]:子数组是 [4,8] ,差绝对值的最小值为 |4-8| = 4 。
- queries[3] = [0,3]:子数组是 [1,3,4,8] ,差的绝对值的最小值为 |3-4| = 1 。

示例 2:

输入:nums = [4,5,2,2,7,10], queries = [[2,3],[0,2],[0,5],[3,5]]
输出:[-1,1,1,3]
解释:查询结果如下:
- queries[0] = [2,3]:子数组是 [2,2] ,差绝对值的最小值为 -1 ,因为所有元素相等。
- queries[1] = [0,2]:子数组是 [4,5,2] ,差绝对值的最小值为 |4-5| = 1 。
- queries[2] = [0,5]:子数组是 [4,5,2,2,7,10] ,差绝对值的最小值为 |4-5| = 1 。
- queries[3] = [3,5]:子数组是 [2,7,10] ,差绝对值的最小值为 |7-10| = 3 。

 

提示:

  • 2 <= nums.length <= 105
  • 1 <= nums[i] <= 100
  • 1 <= queries.length <= 2 * 104
  • 0 <= li < ri < nums.length

通过代码

高赞题解

方法一:前缀和

提示 $1$

在本题中,数组 $\textit{nums}$ 的元素范围在 $[1, 100]$ 中,这使得对于每一组询问 $\textit{queries}_i = (l_i, r_i)$,我们可以枚举 $[1, 100]$ 中的每一个整数是否出现,并以此计算「差绝对值的最小值」。

提示 $2$

对于任意的数组 $a$,如果 $a$ 已经有序,那么我们只需要对 $a$ 进行一次遍历,得到 $a$ 中相邻两元素的差值中的最小值(不能为 $0$),即为「差绝对值的最小值」。如果 $a$ 中所有元素均相等,那么「差绝对值的最小值」为 $-1$。

思路与算法

我们可以使用前缀和数组 $\textit{pre}[i][c]$ 表示数组 $\textit{nums}$ 的前缀 $a[0..i-1]$ 中包含元素 $c$ 的个数。

对于询问 $\textit{queries}_i = (l_i, r_i)$,如果$\textit{nums}[l_i .. r_i]$ 中包含元素 $c$,那么 $\textit{pre}[r_i+1][c] - \textit{pre}[l_i][c]$ 的值大于 $0$,否则其等于 $0$。

这样一来,根据提示 $1$,我们只需要从小到大在 $[1, 100]$ 中枚举元素 $c$,并通过 $\textit{pre}[r_i+1][c] - \textit{pre}[l_i][c] > 0$ 判断元素 $c$ 是否在 $\textit{nums}[l_i .. r_i]$ 中出现过。这样做就相当于我们对 $\textit{nums}[l_i .. r_i]$ 中的元素无重复地从小到大进行了一次遍历。根据提示 $2$,我们只需要求出相邻两个在 $\textit{nums}[l_i .. r_i]$ 中出现过的元素的差值中的最小值,即为「差绝对值的最小值」。

代码

[sol1-C++]
class Solution { private: // 元素 c 的最大值 static constexpr int C = 100; public: vector<int> minDifference(vector<int>& nums, vector<vector<int>>& queries) { int n = nums.size(); // 前缀和 vector<array<int, C + 1>> pre(n + 1); fill(pre[0].begin(), pre[0].end(), 0); for (int i = 0; i < nums.size(); ++i) { copy_n(pre[i].begin(), C + 1, pre[i + 1].begin()); ++pre[i + 1][nums[i]]; } int q = queries.size(); vector<int> ans; for (int i = 0; i < q; ++i) { int left = queries[i][0], right = queries[i][1]; // last 记录上一个出现的元素 // best 记录相邻两个元素差值的最小值 int last = 0, best = INT_MAX; for (int j = 1; j <= C; ++j) { if (pre[left][j] != pre[right + 1][j]) { if (last) { best = min(best, j - last); } last = j; } } if (best == INT_MAX) { best = -1; } ans.push_back(best); } return ans; } };
[sol1-Python3]
class Solution: def minDifference(self, nums: List[int], queries: List[List[int]]) -> List[int]: # 元素 c 的最大值 C = 100 n = len(nums) # 前缀和 pre = [[0] * (C + 1)] for i, num in enumerate(nums): pre.append(pre[-1][:]) pre[-1][num] += 1 ans = list() for left, right in queries: # last 记录上一个出现的元素 # best 记录相邻两个元素差值的最小值 last = 0 best = float("inf") for j in range(1, C + 1): if pre[left][j] != pre[right + 1][j]: if last != 0: best = min(best, j - last) last = j if best == float("inf"): best = -1 ans.append(best) return ans

复杂度分析

  • 时间复杂度:$O((n+q)C)$,其中 $n$ 和 $q$ 分别是数组 $\textit{nums}$ 和 $\textit{queries}$ 的长度,$C$ 是数组 $\textit{nums}$ 中元素的最大值,在本题中 $C=100$。

    • 我们需要 $O(nC)$ 的时间预处理前缀和;

    • 我们需要 $O(C)$ 的时间,遍历 $[1, C]$ 中的每一个整数来得到一个询问对应的答案。询问一共有 $q$ 个,总时间复杂度为 $O(qC)$。

  • 空间复杂度:$O(nC)$,即为存储前缀和需要使用的空间。

统计信息

通过次数 提交次数 AC比率
2622 6173 42.5%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
1904-你完成的完整对局数(The Number of Full Rounds You Have Played)
下一篇:
1925-统计平方和三元组的数目(Count Square Sum Triples)
本文目录
本文目录