202 快乐数
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
- 方法一:利用哈希集合,来找出循环的出口,如果计算后的和在哈希集合中有出现过,就说明出现了循环,永远不可能是快乐数。
class Solution {
public:
bool isHappy(int n) {
unordered_set<int> tmp;
while(n!=1){
//各位求和
int ans = 0;
while(n>0)
{
ans += (n%10)*(n%10);
n = n /10;
}
n = ans;
if(tmp.count(n)) return false;
tmp.insert(n);
}
return true;
}
};
- 方法二:参考了快慢指针的解法,因为该题归到底也是要判断每次计算的和是否会循环。
class Solution {
public:
int bitSquareSum(int n) {
int sum = 0;
while(n > 0)
{
int bit = n % 10;
sum += bit * bit;
n = n / 10;
}
return sum;
}
bool isHappy(int n) {
int slow = n, fast = n;
do{
slow = bitSquareSum(slow);
fast = bitSquareSum(fast);
fast = bitSquareSum(fast);
}while(slow != fast);
return slow == 1;
}
};
解决冲突的方法
- 开放定址法:线性探测再散列、二次探测再散列、伪随机探测再散列
- 拉链法(705 设计哈希集合)
哈希表+滑动窗口
滑动窗口是数组/字符串问题中常用的方法,和哈希表结合的题目比如3.无重复字符的最长子串这道题用哈希表代替了第二层循环。当
S
i
,
j
S_{i,j}
Si,j这段字符串没有重复,当新来一个
S
j
+
1
S_{j+1}
Sj+1时,不用再像暴力解一样再重新遍历
S
i
,
j
+
1
S_{i,j+1}
Si,j+1看是否有重复,只需判断
S
j
+
1
S_{j+1}
Sj+1有没有在
S
i
,
j
S_{i,j}
Si,j出现过就行。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len = s.size();
unordered_set<char> tmp;
int i=0,j=0,res=0;
while(i<len and j<len){
if(!tmp.count(s[j])){
tmp.insert(s[j++]);
res = max(j-i,res);
}
else tmp.erase(s[i++]);
}
return res;
}
};
但其实可以将滑动窗口进行优化,可以将set改为映射,储存下各字符的位置,这样更新i的时候不用加1,而是直接变到重复字符的下一位。