每日挑战(C++ 算法版)
在这里,我将开始每天练习LeetCode算法题,并将个人解决方案放在这里。
需求介绍
给你一个下标从 0 开始的数组 nums
,数组长度为 n
。
nums
的不同元素数目差 数组可以用一个长度为 n
的数组 diff
表示,其中 diff[i]
等于前缀 nums[0, ..., i]
中不同元素的数目 减去 后缀 nums[i + 1, ..., n - 1]
中不同元素的数目。
返回 nums
的 不同元素数目差 数组。
注意 nums[i, ..., j]
表示 nums
的一个从下标 i
开始到下标 j
结束的子数组(包含下标 i
和 j
对应元素)。特别需要说明的是,如果 i > j
,则 nums[i, ..., j]
表示一个空子数组。
要求:
1 <= n == nums.length <= 50
1 <= nums[i] <= 50
个人分析
看到这个题目,我首先想到的就是使用哈希表进行处理。从算法要求能看出来,这个nums数组的大小并不大,并且nums数组中的元素值范围很小。从要求来看,我选择使用数组作为哈希表(这里我称为为哈希表数组),其中哈希表数组的key为nums数组中元素值的范围,哈希表数组的value为nums数组中的key的数量。
例如:
- nums[1, 2, 3, 4, 5],那么构造的哈希表数组为[0, 1, 1, 1, 1, 1, 0, ...]。
- nums[3, 2, 3, 4, 2],那么构造的哈希表数组为[0, 0, 2, 2, 1, 0, 0, ...]。
这个需求计算前缀中不同元素的数目减去后缀中不同元素的数目。因此核心是在算法上可以将数组分为前缀后缀,分别对前缀与后缀进行计算。
我的想法如下:
- 使用前缀数组与后缀数组进行数据存储。
- 对数组进行遍历,将数据存储在后缀数组中。
- 对数组进行重新遍历,以此将数据从后缀数组中放到前缀数组中。并对数据进行分析,将计算结果放在result中。
实现细节:
- 为了使得代码可读性更高,我将前缀数组与后缀数组分为3个部分。
- 第一个部分就是上文提到的哈希表数组,用来存放该元素的个数。
- 第三个部分是使用一个整型数值,用来保存不同元素的数量。
代码实现
class Solution {
public:
vector<int> distinctDifferenceArray(vector<int>& nums) {
vector<int> result; // 用于存放结果的数组
vector<int> prefix(51); // 前缀哈希表数组
int prefix_num = 0; // 前缀数组中不同元素的个数
vector<int> suffix(51); // 后缀哈希表数组
int suffix_num = 0; // 后数组中不同元素的个数
// 对应第二步
for(int i = 0; i < nums.size(); i++)
{
if(!suffix[nums[i]])
{
suffix_num += 1;
}
suffix[nums[i]] += 1;
}
//对应第三步
for(int i = 0; i < nums.size(); i++)
{
if(!prefix[nums[i]])
{
prefix_num += 1;
}
prefix[nums[i]] += 1;
suffix[nums[i]] -= 1;
if(!suffix[nums[i]])
{
suffix_num -= 1;
}
result.push_back(prefix_num - suffix_num);
}
return result;
}
};
总结
上述代码在leetcode中时间上击败了93.%和内存上21.7%的对手。