我的leetcode之旅--强整数与哈希表
三月你好!
庭院深深深几许,杨柳堆烟,帘幕无重数。玉勒雕鞍游冶处,楼高不见章台路。雨横风狂三月暮,门掩黄昏,无计留春住。泪眼问花花不语,乱红飞过秋千去。——欧阳修《蝶恋花·庭院深深深几许》
强整数(2019.02.28)
题目描述
给定两个非负整数 和 ,如果某一整数等于,其中整数 且 ,那么我们认为该整数是一个强整数。
返回值小于或等于 bound 的所有强整数组成的列表。
你可以按任何顺序返回答案。在你的回答中,每个值最多出现一次。
提示: 1 <= x <= 100
1 <= y <= 100
0 <= bound <= 10^6
示例 :
输入:x = 2, y = 3, bound = 10
输出:[2,3,4,5,7,9,10]
解释:
2 = 2^0 + 3^0
3 = 2^1 + 3^0
4 = 2^0 + 3^1
5 = 2^1 + 3^1
7 = 2^2 + 3^1
9 = 2^3 + 3^0
10 = 2^0 + 3^2
解法分析
通过分析,本题采用暴力**,只要找出、的可取值范围,并对、进行遍历,就可以找出不大于bound的所有强整数,但是在保存结果时需要对当前结果进行查找,保证不重复,为了减小查找的代价,可额外使用哈希表处理。 下面对、的边界进行分析: 如果则输出结果为2;当, ,,所以边界最大可取20,同理的边界也可取20,如果的值更大,则、的边界值应更小,同样满足要求。程序暴力求解的代价其实也不大。
class Solution {
public:
vector<int> powerfulIntegers(int x, int y, int bound) {
vector<int> temp;
unordered_map<int, int> hashmap;
int i,j;
for(i=0;i<20;++i){
for(j=0;j<20;++j){
int v = pow(x,i) + pow(y,j);
if((pow(x,i) + pow(y,j))<=bound )
if(!hashmap[v]){ //哈希表用于判断当前结果中不存在v
temp.push_back(v);
hashmap[v]++;
}
}
}
return temp;
}
};
一句话总结
看似简单的题目我硬是提交了几十次,leetcode网站莫不是有BUG。
哈希表简介
哈希表(Hash Table)又叫散列表,是一种便于程序查找的数据结构,下面我按照自己的理解对哈希表做一个简单的介绍。
比如在C++中有这样一个数组V:
索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
数值 | 265 | 24 | 74 | 16 | 128 | 25 | 37 | 43 |
现在的任务是:想在数组中查找一个数值,如果存在就返回索引。一般的如果数组长度不大,或者查找任务不复杂,直接对数组进行遍历就可以了。但是如果数组规模十分庞大,比如成百万上千万的话,那查找一个数的时间代价就很大了。最理想的查找情况是,你给我一个数,我简单运算就知道这个数应该存放在哪,直接去对应的地址找索引,那就再好不过了。哈希表就是这样的数据结构。针对上述数组V构建下面长度为11哈希表H,构建方法如下:
比如索引0对应的数值是265,265除以11等于24余1,于是把索引0存放在余数的位置,也就是哈希地址为1 处。同理,其他数值的索引依次存放。
这里除数取余的方法被称为哈希函数,这是一种比较简单的哈希函数,被除数一般是素数,数值265被称为键值。
哈希地址 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
记录 (索引) | 0 | 1 | 5 | 6 | 3 | 4 | 2 | 7 | |||
记录对应的数值 | 265 | 24 | 25 | 37 | 16 | 128 | 74 | 43 |
哈希表构造好了以后,想查找一个数比如128,求知道存放在哈希地址7处,在数组中对应的索引是4;查找分析哈希地址9处为空,表示数组中不存在119这个数。
你应该注意到根据哈希函数构造哈希表时,有可能不同的键值得到的哈希地址相同,需要存放在同一处,这称之为哈希冲突。应尽可能避免哈希冲突,如扩大哈希表空间或使用不同的哈希函数以及其他的优化策略。哈希表不只可以处理数字,也可以处理文字等其他的数据类型,只不过哈希函数可能需要自行构造。
简单来说,哈希表是一种用空间换时间的方法,有它的优势比如便于查找,也有他的缺点比如插入或删除数据困难。