2022.8.1今天你刷题了吗?
题目:
给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值。
你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。
分析:
给定一个数组,需要找到里面度最大的元素,然后求出这些元素中能够构成最短连续子数组的大小,情况如下:
【1,2,3,3,1】度最大=2,且包括元素1,3,但是最短连续子数组是3,其长度为2
【1,2,1,3,1】度最大=3,为元素1,最短子数组长度为3.
思路:利用一个哈希表,记录元素,然后找到里面最大的度以及度对应的元素有哪些,然后分别对这些元素进行遍历,求出它们的最短子数组(但是在力扣中出错了,因为数组大小越界被限制),但是思路没问题。
解析:
1.暴力法(有问题)
class Solution {
public:
int findShortestSubArray(vector<int>& nums) {
unordered_map<int, int>map;
vector<int>vec;
int res = 0;
int ans = 0;
int q = 0;
int w = 0;
int e = 0;
int r = 100000;
for (auto num : nums)
{
map[num]++;
res = max(map[num], res);//找到了度的大小
}
e = res;
for (std::unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++)
{
if (it->second == res)
{
ans = it->first;
vec.push_back(ans);//插入度最大的元素,可能有多个
}
}
for (int j=0;j<vec.size();j++)
{
for (int i = 0; i < nums.size(); i++)
{
if (nums[i] == vec[j] && e == res)
{
q = i;
e--;
}
else if (nums[i] == vec[j] && e == 1)
{
w = i;
}
else if (nums[i] == vec[j] && e != res && e != 1)
{
e--;
}
else if (e == 0)
{
r = q+1;
return r;
}
}
e = res;
r = min(r, w - q + 1);
}
return r;
}
};
2.优化
在求度以及对应元素时,利用一个vector容器一次型存放,这样方便后面的计算
class Solution {
public:
int findShortestSubArray(vector<int>& nums) {
unordered_map<int, vector<int>> mp;
int n = nums.size();
for (int i = 0; i < n; i++) {
if (mp.count(nums[i])) {
mp[nums[i]][0]++;
mp[nums[i]][2] = i;
}
else {
mp[nums[i]] = { 1, i, i };
}
}
int maxNum = 0, minLen = 0;
for (auto& [_, vec] : mp) {
if (maxNum < vec[0]) {
maxNum = vec[0];
minLen = vec[2] - vec[1] + 1;
}
else if (maxNum == vec[0]) {
if (minLen > vec[2] - vec[1] + 1) {
minLen = vec[2] - vec[1] + 1;
}
}
}
return minLen;
}
};