[LeetCode]697. Degree of an Array 解题报告(C++)
题目描述
Given a non-empty array of non-negative integers nums
, the degree of this array is defined as the maximum frequency of any one of its elements.
Your task is to find the smallest possible length of a (contiguous) subarray of nums
, that has the same degree as nums
.
Example 1:
Input: [1, 2, 2, 3, 1]
Output: 2
Explanation:
The input array has a degree of 2 because both elements 1 and 2 appear twice.
Of the subarrays that have the same degree:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
The shortest length is 2. So return 2.
Example 2:
Input: [1,2,2,3,1,4,2]
Output: 6
Note:
nums.length
will be between 1 and 50,000.
nums[i]
will be an integer between 0 and 49,999.
题目大意
- 给定一个非空非负的数组, 数组的度定义为: 某个元素出现的最大次数.
- 要求找到一个 长度最小的连续子串! 和给定数组的度相同.
解题思路
方法1:
- 暴力方法:
- 通过哈希表来存储 两个关系!
- 数字的次数的关系
- 数字和 {起始,结束位置}的关系
- 由于这个题目要求最小.将这些信息都记录下来.
- 最后遍历 找到出现出现次数最多的数字(可能多个)
- 再比较找到最小长度
代码实现:
class Solution0 {
public:
int findShortestSubArray(vector<int>& nums) {
unordered_map<int, int> m;
unordered_map<int, pair<int, int>> pos;
int degree = 0;
for (int i = 0; i < nums.size(); i++) {
// 该数字第一次出现,记录下起始位置.
if (++m[nums[i]] == 1) {
pos[nums[i]] = { i,i };
}
else { // 该数字出现不止一次.改变右边界.
pos[nums[i]].second = i;
}
// 更新最大的次数
degree = max(degree, m[nums[i]]);
}
int res = INT_MAX;
for (auto x : m) {
// 找到出现最多的数字. x.first 通过first 找到其左右边界.
if (x.second == degree) {
res = min(pos[x.first].second - pos[x.first].first + 1,res);
}
}
return res;
}
};
方法2:
- 优化算法. 只需要遍历一次数组
- 1 建立每个数字出现次数的哈希表. 2 建立每个数字起始位置的表.
- 在遍历过程中.
- 累计当前数字的出现次数.
- 若某个数字第一个出现,则建立数字与起始位置的映射关系.
- 当前数字的出现次数等于 degree .则更新 res (计算这个数字出现位置到当前的长度与 res比较大小,取消的)
- 当前数字的出现次数大于 degree .则需要更改当前数字左右边界长度作为res.并且更新degree.
代码实现:
class Solution {
public:
int findShortestSubArray(vector<int>& nums) {
int size = nums.size();
int res = INT_MAX;
int degree = 0;
unordered_map<int, int> m, startIdx;
for (int i = 0; i < size; i++) {
m[nums[i]]++; // 次数更新
if (m[nums[i]] == 1) {
// 第一次出现,建立起始位置和数字的映射
startIdx[nums[i]] = i;
}
if(m[nums[i]]==degree) {
// 等于degree,则得到了最远的距离
// 则需要计算最小的长度
res = min(res,i - startIdx[nums[i]] + 1);
}
else if(m[nums[i]]>degree) {
// 出现次数更多.则需要更新 res成为最高次数对应的长度;
res = i - startIdx[nums[i]] + 1;
degree = m[nums[i]];
}
}
return res;
}
};
小结
- 理解题目的意思很重要!!! 需要建立哪些关系!!!
- 哈希表真的很有用!!!